Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
datalux
GitHub Repository: datalux/osintgram
Path: blob/master/src/Osintgram.py
271 views
1
import datetime
2
import json
3
import sys
4
import urllib
5
import os
6
import codecs
7
from pathlib import Path
8
9
import httpx
10
import ssl
11
ssl._create_default_https_context = ssl._create_unverified_context
12
13
from geopy.geocoders import Nominatim
14
from instagram_private_api import Client as AppClient
15
from instagram_private_api import ClientCookieExpiredError, ClientLoginRequiredError, ClientError, ClientThrottledError
16
17
from prettytable import PrettyTable
18
19
from src import printcolors as pc
20
from src import config
21
22
23
class Osintgram:
24
api = None
25
api2 = None
26
geolocator = Nominatim(user_agent="http")
27
user_id = None
28
target_id = None
29
is_private = True
30
following = False
31
target = ""
32
writeFile = False
33
jsonDump = False
34
cli_mode = False
35
output_dir = "output"
36
37
38
def __init__(self, target, is_file, is_json, is_cli, output_dir, clear_cookies):
39
self.output_dir = output_dir or self.output_dir
40
u = config.getUsername()
41
p = config.getPassword()
42
self.clear_cookies(clear_cookies)
43
self.cli_mode = is_cli
44
if not is_cli:
45
print("\nAttempt to login...")
46
self.login(u, p)
47
self.setTarget(target)
48
self.writeFile = is_file
49
self.jsonDump = is_json
50
51
def clear_cookies(self,clear_cookies):
52
if clear_cookies:
53
self.clear_cache()
54
55
def setTarget(self, target):
56
self.target = target
57
user = self.get_user(target)
58
self.target_id = user['id']
59
self.is_private = user['is_private']
60
self.following = self.check_following()
61
self.__printTargetBanner__()
62
self.output_dir = self.output_dir + "/" + str(self.target)
63
Path(self.output_dir).mkdir(parents=True, exist_ok=True)
64
65
def __get_feed__(self):
66
data = []
67
68
result = self.api.user_feed(str(self.target_id))
69
data.extend(result.get('items', []))
70
71
next_max_id = result.get('next_max_id')
72
while next_max_id:
73
results = self.api.user_feed(str(self.target_id), max_id=next_max_id)
74
data.extend(results.get('items', []))
75
next_max_id = results.get('next_max_id')
76
77
return data
78
79
def __get_comments__(self, media_id):
80
comments = []
81
82
result = self.api.media_comments(str(media_id))
83
comments.extend(result.get('comments', []))
84
85
next_max_id = result.get('next_max_id')
86
while next_max_id:
87
results = self.api.media_comments(str(media_id), max_id=next_max_id)
88
comments.extend(results.get('comments', []))
89
next_max_id = results.get('next_max_id')
90
91
return comments
92
93
def __printTargetBanner__(self):
94
pc.printout("\nLogged as ", pc.GREEN)
95
pc.printout(self.api.username, pc.CYAN)
96
pc.printout(". Target: ", pc.GREEN)
97
pc.printout(str(self.target), pc.CYAN)
98
pc.printout(" [" + str(self.target_id) + "]")
99
if self.is_private:
100
pc.printout(" [PRIVATE PROFILE]", pc.BLUE)
101
if self.following:
102
pc.printout(" [FOLLOWING]", pc.GREEN)
103
else:
104
pc.printout(" [NOT FOLLOWING]", pc.RED)
105
106
print('\n')
107
108
def change_target(self):
109
pc.printout("Insert new target username: ", pc.YELLOW)
110
line = input()
111
self.setTarget(line)
112
return
113
114
def get_addrs(self):
115
if self.check_private_profile():
116
return
117
118
pc.printout("Searching for target localizations...\n")
119
120
data = self.__get_feed__()
121
122
locations = {}
123
124
for post in data:
125
if 'location' in post and post['location'] is not None:
126
if 'lat' in post['location'] and 'lng' in post['location']:
127
lat = post['location']['lat']
128
lng = post['location']['lng']
129
locations[str(lat) + ', ' + str(lng)] = post.get('taken_at')
130
131
address = {}
132
for k, v in locations.items():
133
details = self.geolocator.reverse(k)
134
unix_timestamp = datetime.datetime.fromtimestamp(v)
135
address[details.address] = unix_timestamp.strftime('%Y-%m-%d %H:%M:%S')
136
137
sort_addresses = sorted(address.items(), key=lambda p: p[1], reverse=True)
138
139
if len(sort_addresses) > 0:
140
t = PrettyTable()
141
142
t.field_names = ['Post', 'Address', 'time']
143
t.align["Post"] = "l"
144
t.align["Address"] = "l"
145
t.align["Time"] = "l"
146
pc.printout("\nWoohoo! We found " + str(len(sort_addresses)) + " addresses\n", pc.GREEN)
147
148
i = 1
149
150
json_data = {}
151
addrs_list = []
152
153
for address, time in sort_addresses:
154
t.add_row([str(i), address, time])
155
156
if self.jsonDump:
157
addr = {
158
'address': address,
159
'time': time
160
}
161
addrs_list.append(addr)
162
163
i = i + 1
164
165
if self.writeFile:
166
file_name = self.output_dir + "/" + self.target + "_addrs.txt"
167
file = open(file_name, "w")
168
file.write(str(t))
169
file.close()
170
171
if self.jsonDump:
172
json_data['address'] = addrs_list
173
json_file_name = self.output_dir + "/" + self.target + "_addrs.json"
174
with open(json_file_name, 'w') as f:
175
json.dump(json_data, f)
176
177
print(t)
178
else:
179
pc.printout("Sorry! No results found :-(\n", pc.RED)
180
181
def get_captions(self):
182
if self.check_private_profile():
183
return
184
185
pc.printout("Searching for target captions...\n")
186
187
captions = []
188
189
data = self.__get_feed__()
190
counter = 0
191
192
try:
193
for item in data:
194
if "caption" in item:
195
if item["caption"] is not None:
196
text = item["caption"]["text"]
197
captions.append(text)
198
counter = counter + 1
199
sys.stdout.write("\rFound %i" % counter)
200
sys.stdout.flush()
201
202
except AttributeError:
203
pass
204
205
except KeyError:
206
pass
207
208
json_data = {}
209
210
if counter > 0:
211
pc.printout("\nWoohoo! We found " + str(counter) + " captions\n", pc.GREEN)
212
213
file = None
214
215
if self.writeFile:
216
file_name = self.output_dir + "/" + self.target + "_captions.txt"
217
file = open(file_name, "w")
218
219
for s in captions:
220
print(s + "\n")
221
222
if self.writeFile:
223
file.write(s + "\n")
224
225
if self.jsonDump:
226
json_data['captions'] = captions
227
json_file_name = self.output_dir + "/" + self.target + "_followings.json"
228
with open(json_file_name, 'w') as f:
229
json.dump(json_data, f)
230
231
if file is not None:
232
file.close()
233
234
else:
235
pc.printout("Sorry! No results found :-(\n", pc.RED)
236
237
return
238
239
def get_total_comments(self):
240
if self.check_private_profile():
241
return
242
243
pc.printout("Searching for target total comments...\n")
244
245
comments_counter = 0
246
posts = 0
247
248
data = self.__get_feed__()
249
250
for post in data:
251
comments_counter += post['comment_count']
252
posts += 1
253
254
if self.writeFile:
255
file_name = self.output_dir + "/" + self.target + "_comments.txt"
256
file = open(file_name, "w")
257
file.write(str(comments_counter) + " comments in " + str(posts) + " posts\n")
258
file.close()
259
260
if self.jsonDump:
261
json_data = {
262
'comment_counter': comments_counter,
263
'posts': posts
264
}
265
json_file_name = self.output_dir + "/" + self.target + "_comments.json"
266
with open(json_file_name, 'w') as f:
267
json.dump(json_data, f)
268
269
pc.printout(str(comments_counter), pc.MAGENTA)
270
pc.printout(" comments in " + str(posts) + " posts\n")
271
272
def get_comment_data(self):
273
if self.check_private_profile():
274
return
275
276
pc.printout("Retrieving all comments, this may take a moment...\n")
277
data = self.__get_feed__()
278
279
_comments = []
280
t = PrettyTable(['POST ID', 'ID', 'Username', 'Comment'])
281
t.align["POST ID"] = "l"
282
t.align["ID"] = "l"
283
t.align["Username"] = "l"
284
t.align["Comment"] = "l"
285
286
for post in data:
287
post_id = post.get('id')
288
comments = self.api.media_n_comments(post_id)
289
for comment in comments:
290
t.add_row([post_id, comment.get('user_id'), comment.get('user').get('username'), comment.get('text')])
291
comment = {
292
"post_id": post_id,
293
"user_id":comment.get('user_id'),
294
"username": comment.get('user').get('username'),
295
"comment": comment.get('text')
296
}
297
_comments.append(comment)
298
299
print(t)
300
if self.writeFile:
301
file_name = self.output_dir + "/" + self.target + "_comment_data.txt"
302
with open(file_name, 'w') as f:
303
f.write(str(t))
304
f.close()
305
306
if self.jsonDump:
307
file_name_json = self.output_dir + "/" + self.target + "_comment_data.json"
308
with open(file_name_json, 'w') as f:
309
f.write("{ \"Comments\":[ \n")
310
f.write('\n'.join(json.dumps(comment) for comment in _comments) + ',\n')
311
f.write("]} ")
312
313
314
def get_followers(self):
315
if self.check_private_profile():
316
return
317
318
pc.printout("Searching for target followers...\n")
319
320
_followers = []
321
followers = []
322
323
324
rank_token = AppClient.generate_uuid()
325
data = self.api.user_followers(str(self.target_id), rank_token=rank_token)
326
327
_followers.extend(data.get('users', []))
328
329
next_max_id = data.get('next_max_id')
330
while next_max_id:
331
sys.stdout.write("\rCatched %i followers" % len(_followers))
332
sys.stdout.flush()
333
results = self.api.user_followers(str(self.target_id), rank_token=rank_token, max_id=next_max_id)
334
_followers.extend(results.get('users', []))
335
next_max_id = results.get('next_max_id')
336
337
print("\n")
338
339
for user in _followers:
340
u = {
341
'id': user['pk'],
342
'username': user['username'],
343
'full_name': user['full_name']
344
}
345
followers.append(u)
346
347
t = PrettyTable(['ID', 'Username', 'Full Name'])
348
t.align["ID"] = "l"
349
t.align["Username"] = "l"
350
t.align["Full Name"] = "l"
351
352
json_data = {}
353
followings_list = []
354
355
for node in followers:
356
t.add_row([str(node['id']), node['username'], node['full_name']])
357
358
if self.jsonDump:
359
follow = {
360
'id': node['id'],
361
'username': node['username'],
362
'full_name': node['full_name']
363
}
364
followings_list.append(follow)
365
366
if self.writeFile:
367
file_name = self.output_dir + "/" + self.target + "_followers.txt"
368
file = open(file_name, "w")
369
file.write(str(t))
370
file.close()
371
372
if self.jsonDump:
373
json_data['followers'] = followers
374
json_file_name = self.output_dir + "/" + self.target + "_followers.json"
375
with open(json_file_name, 'w') as f:
376
json.dump(json_data, f)
377
378
print(t)
379
380
def get_followings(self):
381
if self.check_private_profile():
382
return
383
384
pc.printout("Searching for target followings...\n")
385
386
_followings = []
387
followings = []
388
389
rank_token = AppClient.generate_uuid()
390
data = self.api.user_following(str(self.target_id), rank_token=rank_token)
391
392
_followings.extend(data.get('users', []))
393
394
next_max_id = data.get('next_max_id')
395
while next_max_id:
396
sys.stdout.write("\rCatched %i followings" % len(_followings))
397
sys.stdout.flush()
398
results = self.api.user_following(str(self.target_id), rank_token=rank_token, max_id=next_max_id)
399
_followings.extend(results.get('users', []))
400
next_max_id = results.get('next_max_id')
401
402
print("\n")
403
404
for user in _followings:
405
u = {
406
'id': user['pk'],
407
'username': user['username'],
408
'full_name': user['full_name']
409
}
410
followings.append(u)
411
412
t = PrettyTable(['ID', 'Username', 'Full Name'])
413
t.align["ID"] = "l"
414
t.align["Username"] = "l"
415
t.align["Full Name"] = "l"
416
417
json_data = {}
418
followings_list = []
419
420
for node in followings:
421
t.add_row([str(node['id']), node['username'], node['full_name']])
422
423
if self.jsonDump:
424
follow = {
425
'id': node['id'],
426
'username': node['username'],
427
'full_name': node['full_name']
428
}
429
followings_list.append(follow)
430
431
if self.writeFile:
432
file_name = self.output_dir + "/" + self.target + "_followings.txt"
433
file = open(file_name, "w")
434
file.write(str(t))
435
file.close()
436
437
if self.jsonDump:
438
json_data['followings'] = followings_list
439
json_file_name = self.output_dir + "/" + self.target + "_followings.json"
440
with open(json_file_name, 'w') as f:
441
json.dump(json_data, f)
442
443
print(t)
444
445
def get_hashtags(self):
446
if self.check_private_profile():
447
return
448
449
pc.printout("Searching for target hashtags...\n")
450
451
hashtags = []
452
counter = 1
453
texts = []
454
455
data = self.api.user_feed(str(self.target_id))
456
texts.extend(data.get('items', []))
457
458
next_max_id = data.get('next_max_id')
459
while next_max_id:
460
results = self.api.user_feed(str(self.target_id), max_id=next_max_id)
461
texts.extend(results.get('items', []))
462
next_max_id = results.get('next_max_id')
463
464
for post in texts:
465
if post['caption'] is not None:
466
caption = post['caption']['text']
467
for s in caption.split():
468
if s.startswith('#'):
469
hashtags.append(s.encode('UTF-8'))
470
counter += 1
471
472
if len(hashtags) > 0:
473
hashtag_counter = {}
474
475
for i in hashtags:
476
if i in hashtag_counter:
477
hashtag_counter[i] += 1
478
else:
479
hashtag_counter[i] = 1
480
481
ssort = sorted(hashtag_counter.items(), key=lambda value: value[1], reverse=True)
482
483
file = None
484
json_data = {}
485
hashtags_list = []
486
487
if self.writeFile:
488
file_name = self.output_dir + "/" + self.target + "_hashtags.txt"
489
file = open(file_name, "w")
490
491
for k, v in ssort:
492
hashtag = str(k.decode('utf-8'))
493
print(str(v) + ". " + hashtag)
494
if self.writeFile:
495
file.write(str(v) + ". " + hashtag + "\n")
496
if self.jsonDump:
497
hashtags_list.append(hashtag)
498
499
if file is not None:
500
file.close()
501
502
if self.jsonDump:
503
json_data['hashtags'] = hashtags_list
504
json_file_name = self.output_dir + "/" + self.target + "_hashtags.json"
505
with open(json_file_name, 'w') as f:
506
json.dump(json_data, f)
507
else:
508
pc.printout("Sorry! No results found :-(\n", pc.RED)
509
510
def get_user_info(self):
511
try:
512
endpoint = 'users/{user_id!s}/full_detail_info/'.format(**{'user_id': self.target_id})
513
content = self.api._call_api(endpoint)
514
515
data = content['user_detail']['user']
516
517
pc.printout("[ID] ", pc.GREEN)
518
pc.printout(str(data['pk']) + '\n')
519
pc.printout("[FULL NAME] ", pc.RED)
520
pc.printout(str(data['full_name']) + '\n')
521
pc.printout("[BIOGRAPHY] ", pc.CYAN)
522
pc.printout(str(data['biography']) + '\n')
523
pc.printout("[FOLLOWED] ", pc.BLUE)
524
pc.printout(str(data['follower_count']) + '\n')
525
pc.printout("[FOLLOW] ", pc.GREEN)
526
pc.printout(str(data['following_count']) + '\n')
527
pc.printout("[BUSINESS ACCOUNT] ", pc.RED)
528
pc.printout(str(data['is_business']) + '\n')
529
if data['is_business']:
530
if not data['can_hide_category']:
531
pc.printout("[BUSINESS CATEGORY] ")
532
pc.printout(str(data['category']) + '\n')
533
pc.printout("[VERIFIED ACCOUNT] ", pc.CYAN)
534
pc.printout(str(data['is_verified']) + '\n')
535
if 'public_email' in data and data['public_email']:
536
pc.printout("[EMAIL] ", pc.BLUE)
537
pc.printout(str(data['public_email']) + '\n')
538
pc.printout("[HD PROFILE PIC] ", pc.GREEN)
539
pc.printout(str(data['hd_profile_pic_url_info']['url']) + '\n')
540
if 'fb_page_call_to_action_id' in data and data['fb_page_call_to_action_id']:
541
pc.printout("[FB PAGE] ", pc.RED)
542
pc.printout(str(data['connected_fb_page']) + '\n')
543
if 'whatsapp_number' in data and data['whatsapp_number']:
544
pc.printout("[WHATSAPP NUMBER] ", pc.GREEN)
545
pc.printout(str(data['whatsapp_number']) + '\n')
546
if 'city_name' in data and data['city_name']:
547
pc.printout("[CITY] ", pc.YELLOW)
548
pc.printout(str(data['city_name']) + '\n')
549
if 'address_street' in data and data['address_street']:
550
pc.printout("[ADDRESS STREET] ", pc.RED)
551
pc.printout(str(data['address_street']) + '\n')
552
if 'contact_phone_number' in data and data['contact_phone_number']:
553
pc.printout("[CONTACT PHONE NUMBER] ", pc.CYAN)
554
pc.printout(str(data['contact_phone_number']) + '\n')
555
556
if self.jsonDump:
557
user = {
558
'id': data['pk'],
559
'full_name': data['full_name'],
560
'biography': data['biography'],
561
'edge_followed_by': data['follower_count'],
562
'edge_follow': data['following_count'],
563
'is_business_account': data['is_business'],
564
'is_verified': data['is_verified'],
565
'profile_pic_url_hd': data['hd_profile_pic_url_info']['url']
566
}
567
if 'public_email' in data and data['public_email']:
568
user['email'] = data['public_email']
569
if 'fb_page_call_to_action_id' in data and data['fb_page_call_to_action_id']:
570
user['connected_fb_page'] = data['fb_page_call_to_action_id']
571
if 'whatsapp_number' in data and data['whatsapp_number']:
572
user['whatsapp_number'] = data['whatsapp_number']
573
if 'city_name' in data and data['city_name']:
574
user['city_name'] = data['city_name']
575
if 'address_street' in data and data['address_street']:
576
user['address_street'] = data['address_street']
577
if 'contact_phone_number' in data and data['contact_phone_number']:
578
user['contact_phone_number'] = data['contact_phone_number']
579
580
json_file_name = self.output_dir + "/" + self.target + "_info.json"
581
with open(json_file_name, 'w') as f:
582
json.dump(user, f)
583
584
except ClientError as e:
585
print(e)
586
pc.printout("Oops... " + str(self.target) + " non exist, please enter a valid username.", pc.RED)
587
pc.printout("\n")
588
exit(2)
589
590
def get_total_likes(self):
591
if self.check_private_profile():
592
return
593
594
pc.printout("Searching for target total likes...\n")
595
596
like_counter = 0
597
posts = 0
598
599
data = self.__get_feed__()
600
601
likes = [int(p["like_count"]) for p in data]
602
posts = len(likes)
603
like_counter = sum(likes)
604
min_ = min(likes)
605
max_ = max(likes)
606
avg = int(like_counter / posts)
607
result = f" likes in {posts} posts (min: {min_}, max: {max_}, avg: {avg})\n"
608
609
if self.writeFile:
610
file_name = self.output_dir + "/" + self.target + "_likes.txt"
611
file = open(file_name, "w")
612
file.write(str(like_counter) + result)
613
file.close()
614
615
if self.jsonDump:
616
json_data = {
617
"like_counter": like_counter,
618
"posts": posts,
619
"min": min_,
620
"max": max_,
621
"avg": avg,
622
}
623
json_file_name = self.output_dir + "/" + self.target + "_likes.json"
624
with open(json_file_name, "w") as f:
625
json.dump(json_data, f)
626
627
pc.printout(str(like_counter), pc.MAGENTA)
628
pc.printout(result)
629
630
def get_media_type(self):
631
if self.check_private_profile():
632
return
633
634
pc.printout("Searching for target captions...\n")
635
636
counter = 0
637
photo_counter = 0
638
video_counter = 0
639
640
data = self.__get_feed__()
641
642
for post in data:
643
if "media_type" in post:
644
if post["media_type"] == 1:
645
photo_counter = photo_counter + 1
646
elif post["media_type"] == 2:
647
video_counter = video_counter + 1
648
counter = counter + 1
649
sys.stdout.write("\rChecked %i" % counter)
650
sys.stdout.flush()
651
652
sys.stdout.write(" posts")
653
sys.stdout.flush()
654
655
if counter > 0:
656
657
if self.writeFile:
658
file_name = self.output_dir + "/" + self.target + "_mediatype.txt"
659
file = open(file_name, "w")
660
file.write(str(photo_counter) + " photos and " + str(video_counter) + " video posted by target\n")
661
file.close()
662
663
pc.printout("\nWoohoo! We found " + str(photo_counter) + " photos and " + str(video_counter) +
664
" video posted by target\n", pc.GREEN)
665
666
if self.jsonDump:
667
json_data = {
668
"photos": photo_counter,
669
"videos": video_counter
670
}
671
json_file_name = self.output_dir + "/" + self.target + "_mediatype.json"
672
with open(json_file_name, 'w') as f:
673
json.dump(json_data, f)
674
675
else:
676
pc.printout("Sorry! No results found :-(\n", pc.RED)
677
678
def get_people_who_commented(self):
679
if self.check_private_profile():
680
return
681
682
pc.printout("Searching for users who commented...\n")
683
684
data = self.__get_feed__()
685
users = []
686
687
for post in data:
688
comments = self.__get_comments__(post['id'])
689
for comment in comments:
690
if not any(u['id'] == comment['user']['pk'] for u in users):
691
user = {
692
'id': comment['user']['pk'],
693
'username': comment['user']['username'],
694
'full_name': comment['user']['full_name'],
695
'counter': 1
696
}
697
users.append(user)
698
else:
699
for user in users:
700
if user['id'] == comment['user']['pk']:
701
user['counter'] += 1
702
break
703
704
if len(users) > 0:
705
ssort = sorted(users, key=lambda value: value['counter'], reverse=True)
706
707
json_data = {}
708
709
t = PrettyTable()
710
711
t.field_names = ['Comments', 'ID', 'Username', 'Full Name']
712
t.align["Comments"] = "l"
713
t.align["ID"] = "l"
714
t.align["Username"] = "l"
715
t.align["Full Name"] = "l"
716
717
for u in ssort:
718
t.add_row([str(u['counter']), u['id'], u['username'], u['full_name']])
719
720
print(t)
721
722
if self.writeFile:
723
file_name = self.output_dir + "/" + self.target + "_users_who_commented.txt"
724
file = open(file_name, "w")
725
file.write(str(t))
726
file.close()
727
728
if self.jsonDump:
729
json_data['users_who_commented'] = ssort
730
json_file_name = self.output_dir + "/" + self.target + "_users_who_commented.json"
731
with open(json_file_name, 'w') as f:
732
json.dump(json_data, f)
733
else:
734
pc.printout("Sorry! No results found :-(\n", pc.RED)
735
736
def get_people_who_tagged(self):
737
if self.check_private_profile():
738
return
739
740
pc.printout("Searching for users who tagged target...\n")
741
742
posts = []
743
744
result = self.api.usertag_feed(self.target_id)
745
posts.extend(result.get('items', []))
746
747
next_max_id = result.get('next_max_id')
748
while next_max_id:
749
results = self.api.user_feed(str(self.target_id), max_id=next_max_id)
750
posts.extend(results.get('items', []))
751
next_max_id = results.get('next_max_id')
752
753
if len(posts) > 0:
754
pc.printout("\nWoohoo! We found " + str(len(posts)) + " photos\n", pc.GREEN)
755
756
users = []
757
758
for post in posts:
759
if not any(u['id'] == post['user']['pk'] for u in users):
760
user = {
761
'id': post['user']['pk'],
762
'username': post['user']['username'],
763
'full_name': post['user']['full_name'],
764
'counter': 1
765
}
766
users.append(user)
767
else:
768
for user in users:
769
if user['id'] == post['user']['pk']:
770
user['counter'] += 1
771
break
772
773
ssort = sorted(users, key=lambda value: value['counter'], reverse=True)
774
775
json_data = {}
776
777
t = PrettyTable()
778
779
t.field_names = ['Photos', 'ID', 'Username', 'Full Name']
780
t.align["Photos"] = "l"
781
t.align["ID"] = "l"
782
t.align["Username"] = "l"
783
t.align["Full Name"] = "l"
784
785
for u in ssort:
786
t.add_row([str(u['counter']), u['id'], u['username'], u['full_name']])
787
788
print(t)
789
790
if self.writeFile:
791
file_name = self.output_dir + "/" + self.target + "_users_who_tagged.txt"
792
file = open(file_name, "w")
793
file.write(str(t))
794
file.close()
795
796
if self.jsonDump:
797
json_data['users_who_tagged'] = ssort
798
json_file_name = self.output_dir + "/" + self.target + "_users_who_tagged.json"
799
with open(json_file_name, 'w') as f:
800
json.dump(json_data, f)
801
else:
802
pc.printout("Sorry! No results found :-(\n", pc.RED)
803
804
def get_photo_description(self):
805
if self.check_private_profile():
806
return
807
808
content = httpx.get("https://www.instagram.com/" + str(self.target) + "/?__a=1")
809
data = content.json()
810
811
dd = data['graphql']['user']['edge_owner_to_timeline_media']['edges']
812
813
if len(dd) > 0:
814
pc.printout("\nWoohoo! We found " + str(len(dd)) + " descriptions\n", pc.GREEN)
815
816
count = 1
817
818
t = PrettyTable(['Photo', 'Description'])
819
t.align["Photo"] = "l"
820
t.align["Description"] = "l"
821
822
json_data = {}
823
descriptions_list = []
824
825
for i in dd:
826
node = i.get('node')
827
descr = node.get('accessibility_caption')
828
t.add_row([str(count), descr])
829
830
if self.jsonDump:
831
description = {
832
'description': descr
833
}
834
descriptions_list.append(description)
835
836
count += 1
837
838
if self.writeFile:
839
file_name = self.output_dir + "/" + self.target + "_photodes.txt"
840
file = open(file_name, "w")
841
file.write(str(t))
842
file.close()
843
844
if self.jsonDump:
845
json_data['descriptions'] = descriptions_list
846
json_file_name = self.output_dir + "/" + self.target + "_descriptions.json"
847
with open(json_file_name, 'w') as f:
848
json.dump(json_data, f)
849
850
print(t)
851
else:
852
pc.printout("Sorry! No results found :-(\n", pc.RED)
853
854
def get_user_photo(self):
855
if self.check_private_profile():
856
return
857
858
limit = -1
859
if self.cli_mode:
860
user_input = ""
861
else:
862
pc.printout("How many photos you want to download (default all): ", pc.YELLOW)
863
user_input = input()
864
865
try:
866
if user_input == "":
867
pc.printout("Downloading all photos available...\n")
868
else:
869
limit = int(user_input)
870
pc.printout("Downloading " + user_input + " photos...\n")
871
872
except ValueError:
873
pc.printout("Wrong value entered\n", pc.RED)
874
return
875
876
data = []
877
counter = 0
878
879
result = self.api.user_feed(str(self.target_id))
880
data.extend(result.get('items', []))
881
882
next_max_id = result.get('next_max_id')
883
while next_max_id:
884
results = self.api.user_feed(str(self.target_id), max_id=next_max_id)
885
data.extend(results.get('items', []))
886
next_max_id = results.get('next_max_id')
887
888
try:
889
for item in data:
890
if counter == limit:
891
break
892
if "image_versions2" in item:
893
counter = counter + 1
894
url = item["image_versions2"]["candidates"][0]["url"]
895
photo_id = item["id"]
896
end = self.output_dir + "/" + self.target + "_" + photo_id + ".jpg"
897
urllib.request.urlretrieve(url, end)
898
sys.stdout.write("\rDownloaded %i" % counter)
899
sys.stdout.flush()
900
else:
901
carousel = item["carousel_media"]
902
for i in carousel:
903
if counter == limit:
904
break
905
counter = counter + 1
906
url = i["image_versions2"]["candidates"][0]["url"]
907
photo_id = i["id"]
908
end = self.output_dir + "/" + self.target + "_" + photo_id + ".jpg"
909
urllib.request.urlretrieve(url, end)
910
sys.stdout.write("\rDownloaded %i" % counter)
911
sys.stdout.flush()
912
913
except AttributeError:
914
pass
915
916
except KeyError:
917
pass
918
919
sys.stdout.write(" photos")
920
sys.stdout.flush()
921
922
pc.printout("\nWoohoo! We downloaded " + str(counter) + " photos (saved in " + self.output_dir + " folder) \n", pc.GREEN)
923
924
def get_user_propic(self):
925
926
try:
927
endpoint = 'users/{user_id!s}/full_detail_info/'.format(**{'user_id': self.target_id})
928
content = self.api._call_api(endpoint)
929
930
data = content['user_detail']['user']
931
932
if "hd_profile_pic_url_info" in data:
933
URL = data["hd_profile_pic_url_info"]['url']
934
else:
935
#get better quality photo
936
items = len(data['hd_profile_pic_versions'])
937
URL = data["hd_profile_pic_versions"][items-1]['url']
938
939
if URL != "":
940
end = self.output_dir + "/" + self.target + "_propic.jpg"
941
urllib.request.urlretrieve(URL, end)
942
pc.printout("Target propic saved in output folder\n", pc.GREEN)
943
944
else:
945
pc.printout("Sorry! No results found :-(\n", pc.RED)
946
947
except ClientError as e:
948
error = json.loads(e.error_response)
949
print(error['message'])
950
print(error['error_title'])
951
exit(2)
952
953
def get_user_stories(self):
954
if self.check_private_profile():
955
return
956
957
pc.printout("Searching for target stories...\n")
958
959
data = self.api.user_reel_media(str(self.target_id))
960
961
counter = 0
962
963
if data['items'] is not None: # no stories avaibile
964
counter = data['media_count']
965
for i in data['items']:
966
story_id = i["id"]
967
if i["media_type"] == 1: # it's a photo
968
url = i['image_versions2']['candidates'][0]['url']
969
end = self.output_dir + "/" + self.target + "_" + story_id + ".jpg"
970
urllib.request.urlretrieve(url, end)
971
972
elif i["media_type"] == 2: # it's a gif or video
973
url = i['video_versions'][0]['url']
974
end = self.output_dir + "/" + self.target + "_" + story_id + ".mp4"
975
urllib.request.urlretrieve(url, end)
976
977
if counter > 0:
978
pc.printout(str(counter) + " target stories saved in output folder\n", pc.GREEN)
979
else:
980
pc.printout("Sorry! No results found :-(\n", pc.RED)
981
982
def get_people_tagged_by_user(self):
983
pc.printout("Searching for users tagged by target...\n")
984
985
ids = []
986
username = []
987
full_name = []
988
post = []
989
counter = 1
990
991
data = self.__get_feed__()
992
993
try:
994
for i in data:
995
if "usertags" in i:
996
c = i.get('usertags').get('in')
997
for cc in c:
998
if cc.get('user').get('pk') not in ids:
999
ids.append(cc.get('user').get('pk'))
1000
username.append(cc.get('user').get('username'))
1001
full_name.append(cc.get('user').get('full_name'))
1002
post.append(1)
1003
else:
1004
index = ids.index(cc.get('user').get('pk'))
1005
post[index] += 1
1006
counter = counter + 1
1007
except AttributeError as ae:
1008
pc.printout("\nERROR: an error occurred: ", pc.RED)
1009
print(ae)
1010
print("")
1011
pass
1012
1013
if len(ids) > 0:
1014
t = PrettyTable()
1015
1016
t.field_names = ['Posts', 'Full Name', 'Username', 'ID']
1017
t.align["Posts"] = "l"
1018
t.align["Full Name"] = "l"
1019
t.align["Username"] = "l"
1020
t.align["ID"] = "l"
1021
1022
pc.printout("\nWoohoo! We found " + str(len(ids)) + " (" + str(counter) + ") users\n", pc.GREEN)
1023
1024
json_data = {}
1025
tagged_list = []
1026
1027
for i in range(len(ids)):
1028
t.add_row([post[i], full_name[i], username[i], str(ids[i])])
1029
1030
if self.jsonDump:
1031
tag = {
1032
'post': post[i],
1033
'full_name': full_name[i],
1034
'username': username[i],
1035
'id': ids[i]
1036
}
1037
tagged_list.append(tag)
1038
1039
if self.writeFile:
1040
file_name = self.output_dir + "/" + self.target + "_tagged.txt"
1041
file = open(file_name, "w")
1042
file.write(str(t))
1043
file.close()
1044
1045
if self.jsonDump:
1046
json_data['tagged'] = tagged_list
1047
json_file_name = self.output_dir + "/" + self.target + "_tagged.json"
1048
with open(json_file_name, 'w') as f:
1049
json.dump(json_data, f)
1050
1051
print(t)
1052
else:
1053
pc.printout("Sorry! No results found :-(\n", pc.RED)
1054
1055
def get_user(self, username):
1056
try:
1057
content = self.api.username_info(username)
1058
if self.writeFile:
1059
file_name = self.output_dir + "/" + self.target + "_user_id.txt"
1060
file = open(file_name, "w")
1061
file.write(str(content['user']['pk']))
1062
file.close()
1063
1064
user = dict()
1065
user['id'] = content['user']['pk']
1066
user['is_private'] = content['user']['is_private']
1067
1068
return user
1069
except ClientError as e:
1070
pc.printout('ClientError {0!s} (Code: {1:d}, Response: {2!s})'.format(e.msg, e.code, e.error_response), pc.RED)
1071
error = json.loads(e.error_response)
1072
if 'message' in error:
1073
print(error['message'])
1074
if 'error_title' in error:
1075
print(error['error_title'])
1076
if 'challenge' in error:
1077
print("Please follow this link to complete the challenge: " + error['challenge']['url'])
1078
sys.exit(2)
1079
1080
1081
def set_write_file(self, flag):
1082
if flag:
1083
pc.printout("Write to file: ")
1084
pc.printout("enabled", pc.GREEN)
1085
pc.printout("\n")
1086
else:
1087
pc.printout("Write to file: ")
1088
pc.printout("disabled", pc.RED)
1089
pc.printout("\n")
1090
1091
self.writeFile = flag
1092
1093
def set_json_dump(self, flag):
1094
if flag:
1095
pc.printout("Export to JSON: ")
1096
pc.printout("enabled", pc.GREEN)
1097
pc.printout("\n")
1098
else:
1099
pc.printout("Export to JSON: ")
1100
pc.printout("disabled", pc.RED)
1101
pc.printout("\n")
1102
1103
self.jsonDump = flag
1104
1105
def login(self, u, p):
1106
try:
1107
settings_file = "config/settings.json"
1108
if not os.path.isfile(settings_file):
1109
# settings file does not exist
1110
print(f'Unable to find file: {settings_file!s}')
1111
1112
# login new
1113
self.api = AppClient(auto_patch=True, authenticate=True, username=u, password=p,
1114
on_login=lambda x: self.onlogin_callback(x, settings_file))
1115
1116
else:
1117
with open(settings_file) as file_data:
1118
cached_settings = json.load(file_data, object_hook=self.from_json)
1119
# print('Reusing settings: {0!s}'.format(settings_file))
1120
1121
# reuse auth settings
1122
self.api = AppClient(
1123
username=u, password=p,
1124
settings=cached_settings,
1125
on_login=lambda x: self.onlogin_callback(x, settings_file))
1126
1127
except (ClientCookieExpiredError, ClientLoginRequiredError) as e:
1128
print(f'ClientCookieExpiredError/ClientLoginRequiredError: {e!s}')
1129
1130
# Login expired
1131
# Do relogin but use default ua, keys and such
1132
self.api = AppClient(auto_patch=True, authenticate=True, username=u, password=p,
1133
on_login=lambda x: self.onlogin_callback(x, settings_file))
1134
1135
except ClientError as e:
1136
pc.printout('ClientError {0!s} (Code: {1:d}, Response: {2!s})'.format(e.msg, e.code, e.error_response), pc.RED)
1137
error = json.loads(e.error_response)
1138
pc.printout(error['message'], pc.RED)
1139
pc.printout(": ", pc.RED)
1140
pc.printout(e.msg, pc.RED)
1141
pc.printout("\n")
1142
if 'challenge' in error:
1143
print("Please follow this link to complete the challenge: " + error['challenge']['url'])
1144
exit(9)
1145
1146
def to_json(self, python_object):
1147
if isinstance(python_object, bytes):
1148
return {'__class__': 'bytes',
1149
'__value__': codecs.encode(python_object, 'base64').decode()}
1150
raise TypeError(repr(python_object) + ' is not JSON serializable')
1151
1152
def from_json(self, json_object):
1153
if '__class__' in json_object and json_object['__class__'] == 'bytes':
1154
return codecs.decode(json_object['__value__'].encode(), 'base64')
1155
return json_object
1156
1157
def onlogin_callback(self, api, new_settings_file):
1158
cache_settings = api.settings
1159
with open(new_settings_file, 'w') as outfile:
1160
json.dump(cache_settings, outfile, default=self.to_json)
1161
# print('SAVED: {0!s}'.format(new_settings_file))
1162
1163
def check_following(self):
1164
if str(self.target_id) == self.api.authenticated_user_id:
1165
return True
1166
endpoint = 'users/{user_id!s}/full_detail_info/'.format(**{'user_id': self.target_id})
1167
return self.api._call_api(endpoint)['user_detail']['user']['friendship_status']['following']
1168
1169
def check_private_profile(self):
1170
if self.is_private and not self.following:
1171
pc.printout("Impossible to execute command: user has private profile\n", pc.RED)
1172
send = input("Do you want send a follow request? [Y/N]: ")
1173
if send.lower() == "y":
1174
self.api.friendships_create(self.target_id)
1175
print("Sent a follow request to target. Use this command after target accepting the request.")
1176
1177
return True
1178
return False
1179
1180
def get_fwersemail(self):
1181
if self.check_private_profile():
1182
return
1183
1184
followers = []
1185
1186
try:
1187
1188
pc.printout("Searching for emails of target followers... this can take a few minutes\n")
1189
1190
rank_token = AppClient.generate_uuid()
1191
data = self.api.user_followers(str(self.target_id), rank_token=rank_token)
1192
1193
for user in data.get('users', []):
1194
u = {
1195
'id': user['pk'],
1196
'username': user['username'],
1197
'full_name': user['full_name']
1198
}
1199
followers.append(u)
1200
1201
next_max_id = data.get('next_max_id')
1202
while next_max_id:
1203
sys.stdout.write("\rCatched %i followers email" % len(followers))
1204
sys.stdout.flush()
1205
results = self.api.user_followers(str(self.target_id), rank_token=rank_token, max_id=next_max_id)
1206
1207
for user in results.get('users', []):
1208
u = {
1209
'id': user['pk'],
1210
'username': user['username'],
1211
'full_name': user['full_name']
1212
}
1213
followers.append(u)
1214
1215
next_max_id = results.get('next_max_id')
1216
1217
print("\n")
1218
1219
results = []
1220
1221
pc.printout("Do you want to get all emails? y/n: ", pc.YELLOW)
1222
value = input()
1223
1224
if value == str("y") or value == str("yes") or value == str("Yes") or value == str("YES"):
1225
value = len(followers)
1226
elif value == str(""):
1227
print("\n")
1228
return
1229
elif value == str("n") or value == str("no") or value == str("No") or value == str("NO"):
1230
while True:
1231
try:
1232
pc.printout("How many emails do you want to get? ", pc.YELLOW)
1233
new_value = int(input())
1234
value = new_value - 1
1235
break
1236
except ValueError:
1237
pc.printout("Error! Please enter a valid integer!", pc.RED)
1238
print("\n")
1239
return
1240
else:
1241
pc.printout("Error! Please enter y/n :-)", pc.RED)
1242
print("\n")
1243
return
1244
1245
for follow in followers:
1246
user = self.api.user_info(str(follow['id']))
1247
if 'public_email' in user['user'] and user['user']['public_email']:
1248
follow['email'] = user['user']['public_email']
1249
if len(results) > value:
1250
break
1251
results.append(follow)
1252
1253
except ClientThrottledError as e:
1254
pc.printout("\nError: Instagram blocked the requests. Please wait a few minutes before you try again.", pc.RED)
1255
pc.printout("\n")
1256
1257
if len(results) > 0:
1258
1259
t = PrettyTable(['ID', 'Username', 'Full Name', 'Email'])
1260
t.align["ID"] = "l"
1261
t.align["Username"] = "l"
1262
t.align["Full Name"] = "l"
1263
t.align["Email"] = "l"
1264
1265
json_data = {}
1266
1267
for node in results:
1268
t.add_row([str(node['id']), node['username'], node['full_name'], node['email']])
1269
1270
if self.writeFile:
1271
file_name = self.output_dir + "/" + self.target + "_fwersemail.txt"
1272
file = open(file_name, "w")
1273
file.write(str(t))
1274
file.close()
1275
1276
if self.jsonDump:
1277
json_data['followers_email'] = results
1278
json_file_name = self.output_dir + "/" + self.target + "_fwersemail.json"
1279
with open(json_file_name, 'w') as f:
1280
json.dump(json_data, f)
1281
1282
print(t)
1283
else:
1284
pc.printout("Sorry! No results found :-(\n", pc.RED)
1285
1286
def get_fwingsemail(self):
1287
if self.check_private_profile():
1288
return
1289
1290
followings = []
1291
1292
try:
1293
1294
pc.printout("Searching for emails of users followed by target... this can take a few minutes\n")
1295
1296
rank_token = AppClient.generate_uuid()
1297
data = self.api.user_following(str(self.target_id), rank_token=rank_token)
1298
1299
for user in data.get('users', []):
1300
u = {
1301
'id': user['pk'],
1302
'username': user['username'],
1303
'full_name': user['full_name']
1304
}
1305
followings.append(u)
1306
1307
next_max_id = data.get('next_max_id')
1308
1309
while next_max_id:
1310
results = self.api.user_following(str(self.target_id), rank_token=rank_token, max_id=next_max_id)
1311
1312
for user in results.get('users', []):
1313
u = {
1314
'id': user['pk'],
1315
'username': user['username'],
1316
'full_name': user['full_name']
1317
}
1318
followings.append(u)
1319
1320
next_max_id = results.get('next_max_id')
1321
1322
results = []
1323
1324
pc.printout("Do you want to get all emails? y/n: ", pc.YELLOW)
1325
value = input()
1326
1327
if value == str("y") or value == str("yes") or value == str("Yes") or value == str("YES"):
1328
value = len(followings)
1329
elif value == str(""):
1330
print("\n")
1331
return
1332
elif value == str("n") or value == str("no") or value == str("No") or value == str("NO"):
1333
while True:
1334
try:
1335
pc.printout("How many emails do you want to get? ", pc.YELLOW)
1336
new_value = int(input())
1337
value = new_value - 1
1338
break
1339
except ValueError:
1340
pc.printout("Error! Please enter a valid integer!", pc.RED)
1341
print("\n")
1342
return
1343
else:
1344
pc.printout("Error! Please enter y/n :-)", pc.RED)
1345
print("\n")
1346
return
1347
1348
for follow in followings:
1349
sys.stdout.write("\rCatched %i followings email" % len(results))
1350
sys.stdout.flush()
1351
user = self.api.user_info(str(follow['id']))
1352
if 'public_email' in user['user'] and user['user']['public_email']:
1353
follow['email'] = user['user']['public_email']
1354
if len(results) > value:
1355
break
1356
results.append(follow)
1357
1358
except ClientThrottledError as e:
1359
pc.printout("\nError: Instagram blocked the requests. Please wait a few minutes before you try again.", pc.RED)
1360
pc.printout("\n")
1361
1362
print("\n")
1363
1364
if len(results) > 0:
1365
t = PrettyTable(['ID', 'Username', 'Full Name', 'Email'])
1366
t.align["ID"] = "l"
1367
t.align["Username"] = "l"
1368
t.align["Full Name"] = "l"
1369
t.align["Email"] = "l"
1370
1371
json_data = {}
1372
1373
for node in results:
1374
t.add_row([str(node['id']), node['username'], node['full_name'], node['email']])
1375
1376
if self.writeFile:
1377
file_name = self.output_dir + "/" + self.target + "_fwingsemail.txt"
1378
file = open(file_name, "w")
1379
file.write(str(t))
1380
file.close()
1381
1382
if self.jsonDump:
1383
json_data['followings_email'] = results
1384
json_file_name = self.output_dir + "/" + self.target + "_fwingsemail.json"
1385
with open(json_file_name, 'w') as f:
1386
json.dump(json_data, f)
1387
1388
print(t)
1389
else:
1390
pc.printout("Sorry! No results found :-(\n", pc.RED)
1391
1392
def get_fwingsnumber(self):
1393
if self.check_private_profile():
1394
return
1395
1396
try:
1397
1398
pc.printout("Searching for phone numbers of users followed by target... this can take a few minutes\n")
1399
1400
followings = []
1401
1402
rank_token = AppClient.generate_uuid()
1403
data = self.api.user_following(str(self.target_id), rank_token=rank_token)
1404
1405
for user in data.get('users', []):
1406
u = {
1407
'id': user['pk'],
1408
'username': user['username'],
1409
'full_name': user['full_name']
1410
}
1411
followings.append(u)
1412
1413
next_max_id = data.get('next_max_id')
1414
1415
while next_max_id:
1416
results = self.api.user_following(str(self.target_id), rank_token=rank_token, max_id=next_max_id)
1417
1418
for user in results.get('users', []):
1419
u = {
1420
'id': user['pk'],
1421
'username': user['username'],
1422
'full_name': user['full_name']
1423
}
1424
followings.append(u)
1425
1426
next_max_id = results.get('next_max_id')
1427
1428
results = []
1429
1430
pc.printout("Do you want to get all phone numbers? y/n: ", pc.YELLOW)
1431
value = input()
1432
1433
if value == str("y") or value == str("yes") or value == str("Yes") or value == str("YES"):
1434
value = len(followings)
1435
elif value == str(""):
1436
print("\n")
1437
return
1438
elif value == str("n") or value == str("no") or value == str("No") or value == str("NO"):
1439
while True:
1440
try:
1441
pc.printout("How many phone numbers do you want to get? ", pc.YELLOW)
1442
new_value = int(input())
1443
value = new_value - 1
1444
break
1445
except ValueError:
1446
pc.printout("Error! Please enter a valid integer!", pc.RED)
1447
print("\n")
1448
return
1449
else:
1450
pc.printout("Error! Please enter y/n :-)", pc.RED)
1451
print("\n")
1452
return
1453
1454
for follow in followings:
1455
sys.stdout.write("\rCatched %i followings phone numbers" % len(results))
1456
sys.stdout.flush()
1457
user = self.api.user_info(str(follow['id']))
1458
if 'contact_phone_number' in user['user'] and user['user']['contact_phone_number']:
1459
follow['contact_phone_number'] = user['user']['contact_phone_number']
1460
if len(results) > value:
1461
break
1462
results.append(follow)
1463
1464
except ClientThrottledError as e:
1465
pc.printout("\nError: Instagram blocked the requests. Please wait a few minutes before you try again.", pc.RED)
1466
pc.printout("\n")
1467
1468
print("\n")
1469
1470
if len(results) > 0:
1471
t = PrettyTable(['ID', 'Username', 'Full Name', 'Phone'])
1472
t.align["ID"] = "l"
1473
t.align["Username"] = "l"
1474
t.align["Full Name"] = "l"
1475
t.align["Phone number"] = "l"
1476
1477
json_data = {}
1478
1479
for node in results:
1480
t.add_row([str(node['id']), node['username'], node['full_name'], node['contact_phone_number']])
1481
1482
if self.writeFile:
1483
file_name = self.output_dir + "/" + self.target + "_fwingsnumber.txt"
1484
file = open(file_name, "w")
1485
file.write(str(t))
1486
file.close()
1487
1488
if self.jsonDump:
1489
json_data['followings_phone_numbers'] = results
1490
json_file_name = self.output_dir + "/" + self.target + "_fwingsnumber.json"
1491
with open(json_file_name, 'w') as f:
1492
json.dump(json_data, f)
1493
1494
print(t)
1495
else:
1496
pc.printout("Sorry! No results found :-(\n", pc.RED)
1497
1498
def get_fwersnumber(self):
1499
if self.check_private_profile():
1500
return
1501
1502
followings = []
1503
1504
try:
1505
1506
pc.printout("Searching for phone numbers of users followers... this can take a few minutes\n")
1507
1508
1509
rank_token = AppClient.generate_uuid()
1510
data = self.api.user_following(str(self.target_id), rank_token=rank_token)
1511
1512
for user in data.get('users', []):
1513
u = {
1514
'id': user['pk'],
1515
'username': user['username'],
1516
'full_name': user['full_name']
1517
}
1518
followings.append(u)
1519
1520
next_max_id = data.get('next_max_id')
1521
1522
while next_max_id:
1523
results = self.api.user_following(str(self.target_id), rank_token=rank_token, max_id=next_max_id)
1524
1525
for user in results.get('users', []):
1526
u = {
1527
'id': user['pk'],
1528
'username': user['username'],
1529
'full_name': user['full_name']
1530
}
1531
followings.append(u)
1532
1533
next_max_id = results.get('next_max_id')
1534
1535
results = []
1536
1537
pc.printout("Do you want to get all phone numbers? y/n: ", pc.YELLOW)
1538
value = input()
1539
1540
if value == str("y") or value == str("yes") or value == str("Yes") or value == str("YES"):
1541
value = len(followings)
1542
elif value == str(""):
1543
print("\n")
1544
return
1545
elif value == str("n") or value == str("no") or value == str("No") or value == str("NO"):
1546
while True:
1547
try:
1548
pc.printout("How many phone numbers do you want to get? ", pc.YELLOW)
1549
new_value = int(input())
1550
value = new_value - 1
1551
break
1552
except ValueError:
1553
pc.printout("Error! Please enter a valid integer!", pc.RED)
1554
print("\n")
1555
return
1556
else:
1557
pc.printout("Error! Please enter y/n :-)", pc.RED)
1558
print("\n")
1559
return
1560
1561
for follow in followings:
1562
sys.stdout.write("\rCatched %i followers phone numbers" % len(results))
1563
sys.stdout.flush()
1564
user = self.api.user_info(str(follow['id']))
1565
if 'contact_phone_number' in user['user'] and user['user']['contact_phone_number']:
1566
follow['contact_phone_number'] = user['user']['contact_phone_number']
1567
if len(results) > value:
1568
break
1569
results.append(follow)
1570
1571
except ClientThrottledError as e:
1572
pc.printout("\nError: Instagram blocked the requests. Please wait a few minutes before you try again.", pc.RED)
1573
pc.printout("\n")
1574
1575
print("\n")
1576
1577
if len(results) > 0:
1578
t = PrettyTable(['ID', 'Username', 'Full Name', 'Phone'])
1579
t.align["ID"] = "l"
1580
t.align["Username"] = "l"
1581
t.align["Full Name"] = "l"
1582
t.align["Phone number"] = "l"
1583
1584
json_data = {}
1585
1586
for node in results:
1587
t.add_row([str(node['id']), node['username'], node['full_name'], node['contact_phone_number']])
1588
1589
if self.writeFile:
1590
file_name = self.output_dir + "/" + self.target + "_fwersnumber.txt"
1591
file = open(file_name, "w")
1592
file.write(str(t))
1593
file.close()
1594
1595
if self.jsonDump:
1596
json_data['followings_phone_numbers'] = results
1597
json_file_name = self.output_dir + "/" + self.target + "_fwerssnumber.json"
1598
with open(json_file_name, 'w') as f:
1599
json.dump(json_data, f)
1600
1601
print(t)
1602
else:
1603
pc.printout("Sorry! No results found :-(\n", pc.RED)
1604
1605
def get_comments(self):
1606
if self.check_private_profile():
1607
return
1608
1609
pc.printout("Searching for users who commented...\n")
1610
1611
data = self.__get_feed__()
1612
users = []
1613
1614
for post in data:
1615
comments = self.__get_comments__(post['id'])
1616
for comment in comments:
1617
print(comment['text'])
1618
1619
# if not any(u['id'] == comment['user']['pk'] for u in users):
1620
# user = {
1621
# 'id': comment['user']['pk'],
1622
# 'username': comment['user']['username'],
1623
# 'full_name': comment['user']['full_name'],
1624
# 'counter': 1
1625
# }
1626
# users.append(user)
1627
# else:
1628
# for user in users:
1629
# if user['id'] == comment['user']['pk']:
1630
# user['counter'] += 1
1631
# break
1632
1633
if len(users) > 0:
1634
ssort = sorted(users, key=lambda value: value['counter'], reverse=True)
1635
1636
json_data = {}
1637
1638
t = PrettyTable()
1639
1640
t.field_names = ['Comments', 'ID', 'Username', 'Full Name']
1641
t.align["Comments"] = "l"
1642
t.align["ID"] = "l"
1643
t.align["Username"] = "l"
1644
t.align["Full Name"] = "l"
1645
1646
for u in ssort:
1647
t.add_row([str(u['counter']), u['id'], u['username'], u['full_name']])
1648
1649
print(t)
1650
1651
if self.writeFile:
1652
file_name = self.output_dir + "/" + self.target + "_users_who_commented.txt"
1653
file = open(file_name, "w")
1654
file.write(str(t))
1655
file.close()
1656
1657
if self.jsonDump:
1658
json_data['users_who_commented'] = ssort
1659
json_file_name = self.output_dir + "/" + self.target + "_users_who_commented.json"
1660
with open(json_file_name, 'w') as f:
1661
json.dump(json_data, f)
1662
else:
1663
pc.printout("Sorry! No results found :-(\n", pc.RED)
1664
1665
def clear_cache(self):
1666
try:
1667
f = open("config/settings.json",'w')
1668
f.write("{}")
1669
pc.printout("Cache Cleared.\n",pc.GREEN)
1670
except FileNotFoundError:
1671
pc.printout("Settings.json don't exist.\n",pc.RED)
1672
finally:
1673
f.close()
1674
1675