@@ -258,6 +258,8 @@ def profile(self, identifier: str) -> Profile:
258
258
# Response actually returns two JSON Objects with profile information,
259
259
# but we'll only use the 1st one for now.
260
260
261
+ with open ("test.json" , "w" , encoding = "utf-8" ) as file : file .write (response .text )
262
+
261
263
information : dict = tuple (json .loads (data ) for data in response .text .strip ().split ("\n " ))[0 ]
262
264
263
265
if information .get ("status" , "" ) != "ok" :
@@ -300,7 +302,6 @@ def direct(self) -> Direct:
300
302
def follow (self , identifier : str ) -> bool :
301
303
"""
302
304
Follows a user
303
- :param self: None
304
305
:param identifier: Username or UserID of target (UserID Recommended)
305
306
:return: Boolean (Followed or not)
306
307
"""
@@ -331,7 +332,6 @@ def follow(self, identifier: str) -> bool:
331
332
def unfollow (self , identifier : str ) -> bool :
332
333
"""
333
334
Unfollows a user by user_id
334
- :param self: None
335
335
:param identifier: Username or UserID of target (UserID Recommended)
336
336
:return: Boolean (Unfollowed or not)
337
337
"""
@@ -362,7 +362,6 @@ def unfollow(self, identifier: str) -> bool:
362
362
def block (self , identifier : str ) -> bool :
363
363
"""
364
364
Blocks a user
365
- :param self: None
366
365
:param identifier: Username or UserID of target (UserID Recommended)
367
366
:return: Boolean (Blocked or not)
368
367
"""
@@ -394,7 +393,6 @@ def block(self, identifier: str) -> bool:
394
393
def unblock (self , identifier : str ) -> bool :
395
394
"""
396
395
Unblocks a user
397
- :param self: None
398
396
:param identifier: Username or UserID of target (UserID Recommended)
399
397
:return: Boolean (Unblocked or not)
400
398
"""
@@ -809,3 +807,59 @@ def comment(self, text: str, media_id: str) -> AddedComment:
809
807
"If not, try using another account, switch "
810
808
"to a different network, or use reputed proxies."
811
809
)
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