| skipped 20 lines |
21 | 21 | | user_id = None |
22 | 22 | | target_id = None |
23 | 23 | | is_private = True |
| 24 | + | following = False |
24 | 25 | | target = "" |
25 | 26 | | writeFile = False |
26 | 27 | | jsonDump = False |
| skipped 12 lines |
39 | 40 | | user = self.get_user(target) |
40 | 41 | | self.target_id = user['id'] |
41 | 42 | | self.is_private = user['is_private'] |
| 43 | + | self.following = self.check_following() |
42 | 44 | | self.__printTargetBanner__() |
43 | 45 | | |
44 | 46 | | def __getUsername__(self): |
| skipped 49 lines |
94 | 96 | | pc.printout(self.api.username, pc.CYAN) |
95 | 97 | | pc.printout(". Target: ", pc.GREEN) |
96 | 98 | | pc.printout(str(self.target), pc.CYAN) |
97 | | - | pc.printout(" [" + str(self.target_id) + "] ") |
| 99 | + | pc.printout(" [" + str(self.target_id) + "]") |
98 | 100 | | if self.is_private: |
99 | | - | pc.printout("[PRIVATE PROFILE]", pc.RED) |
| 101 | + | pc.printout(" [PRIVATE PROFILE]", pc.BLUE) |
| 102 | + | if self.following: |
| 103 | + | pc.printout(" [FOLLOWING]", pc.GREEN) |
| 104 | + | else: |
| 105 | + | pc.printout(" [NOT FOLLOWING]", pc.RED) |
| 106 | + | |
| 107 | + | |
100 | 108 | | print('\n') |
101 | 109 | | |
102 | 110 | | def change_target(self): |
| skipped 3 lines |
106 | 114 | | return |
107 | 115 | | |
108 | 116 | | def get_addrs(self): |
109 | | - | if self.is_private: |
110 | | - | pc.printout("Impossible to execute command: user has private profile\n", pc.RED) |
| 117 | + | if self.check_private_profile(): |
111 | 118 | | return |
112 | 119 | | |
113 | 120 | | pc.printout("Searching for target localizations...\n") |
| skipped 3 lines |
117 | 124 | | locations = {} |
118 | 125 | | |
119 | 126 | | for post in data: |
120 | | - | if post['location'] is not None: |
| 127 | + | if 'location' in post and post['location'] is not None: |
121 | 128 | | lat = post['location']['lat'] |
122 | 129 | | lng = post['location']['lng'] |
123 | 130 | | locations[str(lat) + ', ' + str(lng)] = post.get('taken_at') |
| skipped 49 lines |
173 | 180 | | pc.printout("Sorry! No results found :-(\n", pc.RED) |
174 | 181 | | |
175 | 182 | | def get_captions(self): |
176 | | - | if self.is_private: |
177 | | - | pc.printout("Impossible to execute command: user has private profile\n", pc.RED) |
| 183 | + | if self.check_private_profile(): |
178 | 184 | | return |
179 | 185 | | |
180 | 186 | | pc.printout("Searching for target captions...\n") |
| skipped 51 lines |
232 | 238 | | return |
233 | 239 | | |
234 | 240 | | def get_total_comments(self): |
235 | | - | if self.is_private: |
236 | | - | pc.printout("Impossible to execute command: user has private profile\n", pc.RED) |
| 241 | + | if self.check_private_profile(): |
237 | 242 | | return |
238 | 243 | | |
239 | 244 | | pc.printout("Searching for target total comments...\n") |
| skipped 26 lines |
266 | 271 | | pc.printout(" comments in " + str(posts) + " posts\n") |
267 | 272 | | |
268 | 273 | | def get_followers(self): |
269 | | - | if self.is_private: |
270 | | - | pc.printout("Impossible to execute command: user has private profile\n", pc.RED) |
| 274 | + | if self.check_private_profile(): |
271 | 275 | | return |
272 | 276 | | |
273 | 277 | | pc.printout("Searching for target followers...\n") |
| skipped 45 lines |
319 | 323 | | print(t) |
320 | 324 | | |
321 | 325 | | def get_followings(self): |
322 | | - | if self.is_private: |
323 | | - | pc.printout("Impossible to execute command: user has private profile\n", pc.RED) |
| 326 | + | if self.check_private_profile(): |
324 | 327 | | return |
325 | 328 | | |
326 | 329 | | pc.printout("Searching for target followings...\n") |
| skipped 45 lines |
372 | 375 | | print(t) |
373 | 376 | | |
374 | 377 | | def get_hashtags(self): |
375 | | - | if self.is_private: |
376 | | - | pc.printout("Impossible to execute command: user has private profile\n", pc.RED) |
| 378 | + | if self.check_private_profile(): |
377 | 379 | | return |
378 | 380 | | |
379 | 381 | | pc.printout("Searching for target hashtags...\n") |
| skipped 69 lines |
449 | 451 | | pc.printout(str(data['full_name']) + '\n') |
450 | 452 | | pc.printout("[BIOGRAPHY] ", pc.CYAN) |
451 | 453 | | pc.printout(str(data['biography']) + '\n') |
452 | | - | pc.printout("[FOLLOWED] ", pc.GREEN) |
| 454 | + | pc.printout("[FOLLOWED] ", pc.BLUE) |
453 | 455 | | pc.printout(str(data['edge_followed_by']['count']) + '\n') |
454 | | - | pc.printout("[FOLLOW] ", pc.BLUE) |
| 456 | + | pc.printout("[FOLLOW] ", pc.GREEN) |
455 | 457 | | pc.printout(str(data['edge_follow']['count']) + '\n') |
456 | 458 | | pc.printout("[BUSINESS ACCOUNT] ", pc.RED) |
457 | 459 | | pc.printout(str(data['is_business_account']) + '\n') |
| skipped 2 lines |
460 | 462 | | pc.printout(str(data['business_category_name']) + '\n') |
461 | 463 | | pc.printout("[VERIFIED ACCOUNT] ", pc.CYAN) |
462 | 464 | | pc.printout(str(data['is_verified']) + '\n') |
| 465 | + | if data['business_email']: |
| 466 | + | pc.printout("[BUSINESS EMAIL] ", pc.BLUE) |
| 467 | + | pc.printout(str(data['business_email']) + '\n') |
| 468 | + | pc.printout("[HD PROFILE PIC] ", pc.GREEN) |
| 469 | + | pc.printout(str(data['profile_pic_url_hd']) + '\n') |
| 470 | + | if data['connected_fb_page']: |
| 471 | + | pc.printout("[FB PAGE] ", pc.RED) |
| 472 | + | pc.printout(str(data['business_email']) + '\n') |
463 | 473 | | |
464 | 474 | | if self.jsonDump: |
465 | 475 | | user = { |
| skipped 3 lines |
469 | 479 | | 'edge_followed_by': data['edge_followed_by']['count'], |
470 | 480 | | 'edge_follow': data['edge_follow']['count'], |
471 | 481 | | 'is_business_account': data['is_business_account'], |
472 | | - | 'is_verified': data['is_verified'] |
| 482 | + | 'is_verified': data['is_verified'], |
| 483 | + | 'profile_pic_url_hd': data['profile_pic_url_hd'] |
473 | 484 | | } |
| 485 | + | if data['business_email']: |
| 486 | + | user['business_email'] = data['business_email'] |
| 487 | + | if data['connected_fb_page']: |
| 488 | + | user['connected_fb_page'] = data['connected_fb_page'] |
| 489 | + | |
474 | 490 | | json_file_name = "output/" + self.target + "_info.json" |
475 | 491 | | with open(json_file_name, 'w') as f: |
476 | 492 | | json.dump(user, f) |
| skipped 4 lines |
481 | 497 | | sys.exit(2) |
482 | 498 | | |
483 | 499 | | def get_total_likes(self): |
484 | | - | if self.is_private: |
485 | | - | pc.printout("Impossible to execute command: user has private profile\n", pc.RED) |
| 500 | + | if self.check_private_profile(): |
486 | 501 | | return |
487 | 502 | | |
488 | 503 | | pc.printout("Searching for target total likes...\n") |
| skipped 26 lines |
515 | 530 | | pc.printout(" likes in " + str(posts) + " posts\n") |
516 | 531 | | |
517 | 532 | | def get_media_type(self): |
518 | | - | if self.is_private: |
519 | | - | pc.printout("Impossible to execute command: user has private profile\n", pc.RED) |
| 533 | + | if self.check_private_profile(): |
520 | 534 | | return |
521 | 535 | | |
522 | 536 | | pc.printout("Searching for target captions...\n") |
| skipped 41 lines |
564 | 578 | | pc.printout("Sorry! No results found :-(\n", pc.RED) |
565 | 579 | | |
566 | 580 | | def get_people_who_commented(self): |
567 | | - | if self.is_private: |
568 | | - | pc.printout("Impossible to execute command: user has private profile\n", pc.RED) |
| 581 | + | if self.check_private_profile(): |
569 | 582 | | return |
570 | 583 | | |
571 | 584 | | pc.printout("Searching for users who commented...\n") |
| skipped 50 lines |
622 | 635 | | else: |
623 | 636 | | pc.printout("Sorry! No results found :-(\n", pc.RED) |
624 | 637 | | |
| 638 | + | def get_people_who_tagged(self): |
| 639 | + | if self.check_private_profile(): |
| 640 | + | return |
| 641 | + | |
| 642 | + | pc.printout("Searching for users who tagged target...\n") |
| 643 | + | |
| 644 | + | posts = [] |
| 645 | + | |
| 646 | + | result = self.api.usertag_feed(self.target_id) |
| 647 | + | posts.extend(result.get('items', [])) |
| 648 | + | |
| 649 | + | next_max_id = result.get('next_max_id') |
| 650 | + | while next_max_id: |
| 651 | + | results = self.api.user_feed(str(self.target_id), max_id=next_max_id) |
| 652 | + | posts.extend(results.get('items', [])) |
| 653 | + | next_max_id = results.get('next_max_id') |
| 654 | + | |
| 655 | + | if len(posts) > 0: |
| 656 | + | pc.printout("\nWoohoo! We found " + str(len(posts)) + " photos\n", pc.GREEN) |
| 657 | + | |
| 658 | + | users = [] |
| 659 | + | |
| 660 | + | for post in posts: |
| 661 | + | if not any(u['id'] == post['user']['pk'] for u in users): |
| 662 | + | user = { |
| 663 | + | 'id': post['user']['pk'], |
| 664 | + | 'username': post['user']['username'], |
| 665 | + | 'full_name': post['user']['full_name'], |
| 666 | + | 'counter': 1 |
| 667 | + | } |
| 668 | + | users.append(user) |
| 669 | + | else: |
| 670 | + | for user in users: |
| 671 | + | if user['id'] == post['user']['pk']: |
| 672 | + | user['counter'] += 1 |
| 673 | + | break |
| 674 | + | |
| 675 | + | ssort = sorted(users, key=lambda value: value['counter'], reverse=True) |
| 676 | + | |
| 677 | + | json_data = {} |
| 678 | + | |
| 679 | + | t = PrettyTable() |
| 680 | + | |
| 681 | + | t.field_names = ['Photos', 'ID', 'Username', 'Full Name'] |
| 682 | + | t.align["Photos"] = "l" |
| 683 | + | t.align["ID"] = "l" |
| 684 | + | t.align["Username"] = "l" |
| 685 | + | t.align["Full Name"] = "l" |
| 686 | + | |
| 687 | + | for u in ssort: |
| 688 | + | t.add_row([str(u['counter']), u['id'], u['username'], u['full_name']]) |
| 689 | + | |
| 690 | + | print(t) |
| 691 | + | |
| 692 | + | if self.writeFile: |
| 693 | + | file_name = "output/" + self.target + "_users_who_tagged.txt" |
| 694 | + | file = open(file_name, "w") |
| 695 | + | file.write(str(t)) |
| 696 | + | file.close() |
| 697 | + | |
| 698 | + | if self.jsonDump: |
| 699 | + | json_data['users_who_tagged'] = ssort |
| 700 | + | json_file_name = "output/" + self.target + "_users_who_tagged.json" |
| 701 | + | with open(json_file_name, 'w') as f: |
| 702 | + | json.dump(json_data, f) |
| 703 | + | else: |
| 704 | + | pc.printout("Sorry! No results found :-(\n", pc.RED) |
| 705 | + | |
625 | 706 | | def get_photo_description(self): |
626 | | - | if self.is_private: |
627 | | - | pc.printout("Impossible to execute command: user has private profile\n", pc.RED) |
| 707 | + | if self.check_private_profile(): |
628 | 708 | | return |
629 | 709 | | |
630 | 710 | | content = urllib.request.urlopen("https://www.instagram.com/" + str(self.target) + "/?__a=1") |
| skipped 42 lines |
673 | 753 | | pc.printout("Sorry! No results found :-(\n", pc.RED) |
674 | 754 | | |
675 | 755 | | def get_user_photo(self): |
676 | | - | if self.is_private: |
677 | | - | pc.printout("Impossible to execute command: user has private profile\n", pc.RED) |
| 756 | + | if self.check_private_profile(): |
678 | 757 | | return |
679 | 758 | | |
680 | 759 | | limit = -1 |
| skipped 83 lines |
764 | 843 | | sys.exit(2) |
765 | 844 | | |
766 | 845 | | def get_user_stories(self): |
767 | | - | if self.is_private: |
768 | | - | pc.printout("Impossible to execute command: user has private profile\n", pc.RED) |
| 846 | + | if self.check_private_profile(): |
769 | 847 | | return |
770 | 848 | | |
771 | 849 | | pc.printout("Searching for target stories...\n") |
| skipped 197 lines |
969 | 1047 | | json.dump(cache_settings, outfile, default=self.to_json) |
970 | 1048 | | #print('SAVED: {0!s}'.format(new_settings_file)) |
971 | 1049 | | |
| 1050 | + | def check_following(self): |
| 1051 | + | endpoint = 'users/{user_id!s}/full_detail_info/'.format(**{'user_id': self.target_id}) |
| 1052 | + | return self.api._call_api(endpoint)['user_detail']['user']['friendship_status']['following'] |
| 1053 | + | |
| 1054 | + | def check_private_profile(self): |
| 1055 | + | if self.is_private and not self.following: |
| 1056 | + | pc.printout("Impossible to execute command: user has private profile\n", pc.RED) |
| 1057 | + | return True |
| 1058 | + | return False |
| 1059 | + | |
| 1060 | + | def get_fwersemail(self): |
| 1061 | + | if self.check_private_profile(): |
| 1062 | + | return |
| 1063 | + | |
| 1064 | + | pc.printout("Searching for emails of target followers... this can take a few minutes\n") |
| 1065 | + | |
| 1066 | + | followers = [] |
| 1067 | + | |
| 1068 | + | rank_token = AppClient.generate_uuid() |
| 1069 | + | data = self.api.user_followers(str(self.target_id), rank_token=rank_token) |
| 1070 | + | |
| 1071 | + | for user in data['users']: |
| 1072 | + | u = { |
| 1073 | + | 'id': user['pk'], |
| 1074 | + | 'username': user['username'], |
| 1075 | + | 'full_name': user['full_name'] |
| 1076 | + | } |
| 1077 | + | followers.append(u) |
| 1078 | + | |
| 1079 | + | results = [] |
| 1080 | + | |
| 1081 | + | for follow in followers: |
| 1082 | + | req = urllib.request.urlopen("https://www.instagram.com/" + str(follow['username']) + "/?__a=1") |
| 1083 | + | data = json.load(req)['graphql']['user'] |
| 1084 | + | if data['business_email']: |
| 1085 | + | follow['email'] = data['business_email'] |
| 1086 | + | results.append(follow) |
| 1087 | + | |
| 1088 | + | if len(results) > 0: |
| 1089 | + | |
| 1090 | + | t = PrettyTable(['ID', 'Username', 'Full Name', 'Email']) |
| 1091 | + | t.align["ID"] = "l" |
| 1092 | + | t.align["Username"] = "l" |
| 1093 | + | t.align["Full Name"] = "l" |
| 1094 | + | t.align["Email"] = "l" |
| 1095 | + | |
| 1096 | + | json_data = {} |
| 1097 | + | |
| 1098 | + | for node in results: |
| 1099 | + | t.add_row([str(node['id']), node['username'], node['full_name'], node['email']]) |
| 1100 | + | |
| 1101 | + | if self.writeFile: |
| 1102 | + | file_name = "output/" + self.target + "_followers.txt" |
| 1103 | + | file = open(file_name, "w") |
| 1104 | + | file.write(str(t)) |
| 1105 | + | file.close() |
| 1106 | + | |
| 1107 | + | if self.jsonDump: |
| 1108 | + | json_data['followers'] = results |
| 1109 | + | json_file_name = "output/" + self.target + "_followers.json" |
| 1110 | + | with open(json_file_name, 'w') as f: |
| 1111 | + | json.dump(json_data, f) |
| 1112 | + | |
| 1113 | + | print(t) |
| 1114 | + | else: |
| 1115 | + | pc.printout("Sorry! No results found :-(\n", pc.RED) |
| 1116 | + | |
| 1117 | + | |
| 1118 | + | |
| 1119 | + | |
| 1120 | + | |
| 1121 | + | |
| 1122 | + | |
| 1123 | + | |
| 1124 | + | |
| 1125 | + | |