1111
1212from instagrapi import Client
1313from instagrapi .utils import gen_password
14- from instagrapi .exceptions import (
15- BadCredentials ,
16- DirectThreadNotFound ,
17- ProxyAddressIsBlocked ,
18- BadPassword ,
19- )
14+ from instagrapi .exceptions import DirectThreadNotFound
15+
2016from instagrapi .story import StoryBuilder
2117from instagrapi .types import (
2218 Account ,
@@ -129,13 +125,15 @@ def setup_method(self, *args, **kwargs):
129125 self .cl = self .fresh_account ()
130126
131127 def fresh_account (self ):
132- acc = requests .get (TEST_ACCOUNTS_URL ).json ()[0 ]
133- print ("New fresh account %(username)r" % acc )
128+ acc = requests .get (TEST_ACCOUNTS_URL , verify = False ).json ()[0 ]
129+ print ("New fresh account %(username)r (proxy: %(proxy)r) " % acc )
134130 settings = acc ["client_settings" ]
135131 totp_seed = settings .pop ("totp_seed" , None )
136132 cl = Client (settings = settings , proxy = acc ["proxy" ])
137133 if totp_seed :
138134 totp_code = cl .totp_generate_code (totp_seed )
135+ if sessionid := settings .get ("authorization_data" , {}).get ("sessionid" ):
136+ cl .login_by_sessionid (sessionid )
139137 cl .login (
140138 acc ["username" ],
141139 acc ["password" ],
@@ -1123,139 +1121,151 @@ def test_direct_thread_by_participants(self):
11231121
11241122class ClientDirectMessageTypesTestCase (ClientPrivateTestCase ):
11251123 """Test that DirectMessage and DirectThread fields use structured Pydantic models instead of raw dictionaries"""
1126-
1124+
11271125 def test_direct_message_reactions_model (self ):
11281126 """Test that DirectMessage.reactions field uses MessageReactions model"""
11291127 from instagrapi .types import MessageReactions , MessageReaction
11301128 from datetime import datetime
1131-
1129+
11321130 # Get some direct messages
11331131 threads = self .cl .direct_threads (amount = 5 )
11341132 if not threads :
11351133 self .skipTest ("No direct threads available for testing" )
1136-
1134+
11371135 for thread in threads :
11381136 messages = self .cl .direct_messages (thread .id , amount = 10 )
11391137 for message in messages :
11401138 if message .reactions :
11411139 # Test that reactions field is now a MessageReactions object
11421140 self .assertIsInstance (message .reactions , MessageReactions )
1143-
1141+
11441142 # Test that reactions have proper structure
1145- if hasattr (message .reactions , 'emojis' ) and message .reactions .emojis :
1143+ if (
1144+ hasattr (message .reactions , "emojis" )
1145+ and message .reactions .emojis
1146+ ):
11461147 for emoji_reaction in message .reactions .emojis :
11471148 self .assertIsInstance (emoji_reaction , MessageReaction )
11481149 self .assertIsInstance (emoji_reaction .emoji , str )
11491150 self .assertIsInstance (emoji_reaction .sender_id , str )
11501151 self .assertIsInstance (emoji_reaction .timestamp , datetime )
1151-
1152+
11521153 # Test backward compatibility - should still work as dict
1153- if hasattr (message .reactions , ' likes_count' ):
1154+ if hasattr (message .reactions , " likes_count" ):
11541155 self .assertIsInstance (message .reactions .likes_count , int )
1155-
1156+
11561157 return # Found one message with reactions, test passed
1157-
1158+
11581159 def test_direct_message_link_model (self ):
11591160 """Test that DirectMessage.link field uses MessageLink model"""
11601161 from instagrapi .types import MessageLink , LinkContext
1161-
1162+
11621163 # Get some direct messages
11631164 threads = self .cl .direct_threads (amount = 5 )
11641165 if not threads :
11651166 self .skipTest ("No direct threads available for testing" )
1166-
1167+
11671168 for thread in threads :
11681169 messages = self .cl .direct_messages (thread .id , amount = 10 )
11691170 for message in messages :
11701171 if message .link :
11711172 # Test that link field is now a MessageLink object
11721173 self .assertIsInstance (message .link , MessageLink )
1173-
1174+
11741175 # Test that link has proper structure
1175- if hasattr (message .link , ' text' ):
1176+ if hasattr (message .link , " text" ):
11761177 self .assertIsInstance (message .link .text , str )
1177-
1178- if hasattr (message .link , 'link_context' ) and message .link .link_context :
1178+
1179+ if (
1180+ hasattr (message .link , "link_context" )
1181+ and message .link .link_context
1182+ ):
11791183 self .assertIsInstance (message .link .link_context , LinkContext )
1180- if hasattr (message .link .link_context , 'link_url' ):
1181- self .assertIsInstance (message .link .link_context .link_url , str )
1182-
1184+ if hasattr (message .link .link_context , "link_url" ):
1185+ self .assertIsInstance (
1186+ message .link .link_context .link_url , str
1187+ )
1188+
11831189 return # Found one message with link, test passed
1184-
1190+
11851191 def test_direct_message_visual_media_model (self ):
11861192 """Test that DirectMessage.visual_media field uses VisualMedia model"""
11871193 from instagrapi .types import VisualMedia , VisualMediaContent
1188-
1194+
11891195 # Get some direct messages
11901196 threads = self .cl .direct_threads (amount = 5 )
11911197 if not threads :
11921198 self .skipTest ("No direct threads available for testing" )
1193-
1199+
11941200 for thread in threads :
11951201 messages = self .cl .direct_messages (thread .id , amount = 10 )
11961202 for message in messages :
11971203 if message .visual_media :
11981204 # Test that visual_media field is now a VisualMedia object
11991205 self .assertIsInstance (message .visual_media , VisualMedia )
1200-
1206+
12011207 # Test that visual_media has proper structure
1202- if hasattr (message .visual_media , 'media' ) and message .visual_media .media :
1203- self .assertIsInstance (message .visual_media .media , VisualMediaContent )
1204-
1208+ if (
1209+ hasattr (message .visual_media , "media" )
1210+ and message .visual_media .media
1211+ ):
1212+ self .assertIsInstance (
1213+ message .visual_media .media , VisualMediaContent
1214+ )
1215+
12051216 return # Found one message with visual media, test passed
1206-
1217+
12071218 def test_direct_thread_last_seen_at_model (self ):
12081219 """Test that DirectThread.last_seen_at field uses LastSeenInfo model"""
12091220 from instagrapi .types import LastSeenInfo
12101221 from datetime import datetime
1211-
1222+
12121223 # Get some direct threads
12131224 threads = self .cl .direct_threads (amount = 5 )
12141225 if not threads :
12151226 self .skipTest ("No direct threads available for testing" )
1216-
1227+
12171228 for thread in threads :
12181229 if thread .last_seen_at :
12191230 # Test that last_seen_at is now a dict of LastSeenInfo objects
12201231 for user_id , seen_info in thread .last_seen_at .items ():
12211232 self .assertIsInstance (user_id , str )
12221233 self .assertIsInstance (seen_info , LastSeenInfo )
1223-
1234+
12241235 # Test structure of LastSeenInfo
1225- if hasattr (seen_info , ' timestamp' ):
1236+ if hasattr (seen_info , " timestamp" ):
12261237 self .assertIsInstance (seen_info .timestamp , datetime )
1227- if hasattr (seen_info , ' created_at' ):
1238+ if hasattr (seen_info , " created_at" ):
12281239 self .assertIsInstance (seen_info .created_at , datetime )
1229-
1240+
12301241 return # Found one thread with last_seen_at, test passed
1231-
1242+
12321243 def test_direct_message_clips_metadata_model (self ):
12331244 """Test that DirectMessage.clips_metadata field uses ClipsMetadata model"""
12341245 from instagrapi .types import ClipsMetadata
1235-
1246+
12361247 # Get some direct messages
12371248 threads = self .cl .direct_threads (amount = 5 )
12381249 if not threads :
12391250 self .skipTest ("No direct threads available for testing" )
1240-
1251+
12411252 for thread in threads :
12421253 messages = self .cl .direct_messages (thread .id , amount = 10 )
12431254 for message in messages :
12441255 if message .clips_metadata :
12451256 # Test that clips_metadata field is now a ClipsMetadata object
12461257 self .assertIsInstance (message .clips_metadata , ClipsMetadata )
1247-
1258+
12481259 return # Found one message with clips metadata, test passed
1249-
1260+
12501261 def test_thread_is_seen_datetime_compatibility (self ):
12511262 """Test that DirectThread.is_seen() works with datetime objects"""
1252- from datetime import datetime
1253-
1263+
12541264 # Get some direct threads
12551265 threads = self .cl .direct_threads (amount = 5 )
12561266 if not threads :
12571267 self .skipTest ("No direct threads available for testing" )
1258-
1268+
12591269 for thread in threads :
12601270 if thread .last_seen_at :
12611271 # Test that is_seen method works with datetime objects
@@ -1266,14 +1276,14 @@ def test_thread_is_seen_datetime_compatibility(self):
12661276 return # Successfully tested is_seen method
12671277 except Exception as e :
12681278 self .fail (f"is_seen() method failed with datetime objects: { e } " )
1269-
1279+
12701280 def test_backward_compatibility_dict_access (self ):
12711281 """Test that dict-style access patterns still work for backward compatibility"""
12721282 # Get some direct messages
12731283 threads = self .cl .direct_threads (amount = 5 )
12741284 if not threads :
12751285 self .skipTest ("No direct threads available for testing" )
1276-
1286+
12771287 for thread in threads :
12781288 messages = self .cl .direct_messages (thread .id , amount = 10 )
12791289 for message in messages :
@@ -1282,14 +1292,14 @@ def test_backward_compatibility_dict_access(self):
12821292 try :
12831293 if message .reactions :
12841294 # Should work even though it's now a Pydantic model
1285- likes_count = getattr (message .reactions , ' likes_count' , 0 )
1295+ likes_count = getattr (message .reactions , " likes_count" , 0 )
12861296 self .assertIsInstance (likes_count , int )
1287-
1297+
12881298 if message .link :
12891299 # Should work even though it's now a Pydantic model
1290- link_text = getattr (message .link , ' text' , '' )
1300+ link_text = getattr (message .link , " text" , "" )
12911301 self .assertIsInstance (link_text , str )
1292-
1302+
12931303 return # Successfully tested backward compatibility
12941304 except Exception as e :
12951305 self .fail (f"Backward compatibility test failed: { e } " )
@@ -1418,34 +1428,34 @@ def test_location_medias_recent(self):
14181428
14191429
14201430class SignUpTestCase (unittest .TestCase ):
1421-
14221431 def test_password_enrypt (self ):
14231432 cl = Client ()
1424- enc_password = cl .password_encrypt (' test' )
1425- parts = enc_password .split (':' )
1426- self .assertEqual (parts [0 ], ' #PWD_INSTAGRAM' )
1427- self .assertEqual (parts [1 ], '4' )
1433+ enc_password = cl .password_encrypt (" test" )
1434+ parts = enc_password .split (":" )
1435+ self .assertEqual (parts [0 ], " #PWD_INSTAGRAM" )
1436+ self .assertEqual (parts [1 ], "4" )
14281437 self .assertTrue (int (parts [2 ]) > 1607612345 )
14291438 self .assertTrue (len (parts [3 ]) == 392 )
14301439
14311440 def test_signup (self ):
14321441 cl = Client ()
14331442 username = gen_password ()
14341443 password = gen_password (12 , symbols = True )
1435- email = f' { username } @gmail.com'
1444+ email = f" { username } @gmail.com"
14361445 phone_number = os .environ .get ("IG_PHONE_NUMBER" )
1437- full_name = f' John { username } '
1446+ full_name = f" John { username } "
14381447 user = cl .signup (
1439- username , password , email , phone_number , full_name ,
1448+ username ,
1449+ password ,
1450+ email ,
1451+ phone_number ,
1452+ full_name ,
14401453 year = random .randint (1980 , 1990 ),
14411454 month = random .randint (1 , 12 ),
1442- day = random .randint (1 , 30 )
1455+ day = random .randint (1 , 30 ),
14431456 )
14441457 self .assertIsInstance (user , UserShort )
1445- for key , val in {
1446- "username" : username ,
1447- "full_name" : full_name
1448- }.items ():
1458+ for key , val in {"username" : username , "full_name" : full_name }.items ():
14491459 self .assertEqual (getattr (user , key ), val )
14501460 self .assertTrue (user .profile_pic_url .startswith ("https://" ))
14511461
0 commit comments