Projects STRLCPY Osintgram Commits 0c8c4cef
🤬
Revision indexing in progress... (symbol navigation in revisions will be accurate after indexed)
  • .img/banner.png
  • ■ ■ ■ ■ ■ ■
    README.md
    1  -[![](https://img.shields.io/badge/version-0.7-green)](https://github.com/Datalux/Osintgram/releases/tag/0.7)
     1 +[![](https://img.shields.io/badge/version-0.8-green)](https://github.com/Datalux/Osintgram/releases/tag/0.8)
    2 2  [![](https://img.shields.io/badge/license-GPLv3-blue)](https://img.shields.io/badge/license-GPLv3-blue)
    3 3  [![](https://img.shields.io/badge/language-Python3-red)](https://img.shields.io/badge/language-Python3-red)
    4 4   
    skipped 22 lines
    27 27  - tagged Get list of users tagged by target
    28 28  - target Set new target
    29 29  - wcommented Get a list of user who commented target's photos
     30 +- wtagged Get a list of user who tagged target
    30 31  ```
    31  -You can find detailed commands usage [here](commands.md).
     32 +You can find detailed commands usage [here](doc/COMMANDS.md).
    32 33   
    33  -[**Latest version**](https://github.com/Datalux/Osintgram/releases/tag/0.7) |
    34  -[CHANGELOG](CHANGELOG.md)
     34 +[**Latest version**](https://github.com/Datalux/Osintgram/releases/tag/0.8) |
     35 +[CHANGELOG](doc/CHANGELOG.md)
    35 36   
    36 37  ## Tools
    37 38  <p align="center">
    38  -<img align="center" src="cmd.png" width="600">
     39 +<img align="center" src=".img/banner.png" width="700">
    39 40  </p>
    40 41   
    41 42   
    skipped 30 lines
    72 73  You can propose a feature request opening an issue or a pull request.
    73 74   
    74 75  ## External library
    75  -Instagram API: https://github.com/ping/instagram_private_api
     76 +Instagram API: https://gDOCithub.com/ping/instagram_private_api
     77 + 
  • cmd.png
  • ■ ■ ■ ■ ■ ■
    CHANGELOG.md doc/CHANGELOG.md
    1 1  # Changelog
    2 2   
     3 +## [0.8](https://github.com/Datalux/Osintgram/releases/tag/0.8)
     4 + 
     5 +**Enhancements**
     6 +- Added `wtagged` command (#38)
     7 +- Access private profiles if you following targets (#37)
     8 +- Added more info in `info` command (#36)
     9 + 
     10 +**Bug fixes**
     11 +- Minor bug fix in `addrs` commands (9b9086a)
     12 + 
     13 + 
    3 14  ## [0.7](https://github.com/Datalux/Osintgram/releases/tag/0.7)
    4 15   
    5 16  **Enhancements**
    skipped 68 lines
  • ■ ■ ■ ■ ■ ■
    commands.md doc/COMMANDS.md
    skipped 14 lines
    15 15  - stories Download user's stories
    16 16  - tagged Get list of users tagged by target
    17 17  - wcommented Get a list of user who commented target's photos
     18 +- wtagged Get a list of user who tagged target
    18 19  ```
    19 20   
    20 21  ### addrs
    skipped 35 lines
    56 57  - is business account?
    57 58  - business catagory (if target has business account)
    58 59  - is verified?
     60 +- business email (if available)
     61 +- HD profile picture url
     62 +- connected Facebook page (if available)
    59 63   
    60 64  ### JSON
    61 65  Can set preference to export commands output as JSON in output folder. It save output in `<target username>_<command>.JSON` file.
    skipped 35 lines
    97 101  ## wcommented
    98 102  Return a list of users who commented target's photos sorted by number of comments
    99 103   
     104 +## wtagged
     105 +Return a list of users who tagged target sorted by number of photos
    100 106   
    101 107   
    102 108   
  • doc/doc.pdf
    Binary file.
  • ■ ■ ■ ■ ■
    main.py
    skipped 15 lines
    16 16   pc.printout("\_______ /____ >__|___| /__| \___ /|__| (____ /__|_| /\n", pc.YELLOW)
    17 17   pc.printout(" \/ \/ \/ /_____/ \/ \/ \n", pc.YELLOW)
    18 18   print('\n')
    19  - pc.printout("Version 0.7 - Developed by Giuseppe Criscione - 2019\n\n", pc.YELLOW)
     19 + pc.printout("Version 0.8 - Developed by Giuseppe Criscione - 2019\n\n", pc.YELLOW)
    20 20   pc.printout("Type 'list' to show all allowed commands\n")
    21 21   pc.printout("Type 'FILE=y' to save results to files like '<target username>_<command>.txt (deafult is disabled)'\n")
    22 22   pc.printout("Type 'FILE=n' to disable saving to files'\n")
    skipped 17 lines
    40 40   print("Get target followers")
    41 41   pc.printout("followings\t")
    42 42   print("Get users followed by target")
     43 + pc.printout("fwersemail\t")
     44 + print("Get email of users followed by target")
    43 45   pc.printout("hashtags\t")
    44 46   print("Get hashtags used by target")
    45 47   pc.printout("info\t\t")
    skipped 16 lines
    62 64   print("Set new target")
    63 65   pc.printout("wcommented\t")
    64 66   print("Get a list of user who commented target's photos")
     67 + pc.printout("wtagged\t\t")
     68 + print("Get a list of user who tagged target")
    65 69   
    66 70   
    67 71  def signal_handler(sig, frame):
    skipped 34 lines
    102 106   api.get_followers()
    103 107   elif cmd == "followings":
    104 108   api.get_followings()
     109 + elif cmd == 'fwersemail':
     110 + api.get_fwersemail()
    105 111   elif cmd == "hashtags":
    106 112   api.get_hashtags()
    107 113   elif cmd == "info":
    skipped 16 lines
    124 130   api.change_target()
    125 131   elif cmd == "wcommented":
    126 132   api.get_people_who_commented()
     133 + elif cmd == "wtagged":
     134 + api.get_people_who_tagged()
    127 135   elif cmd == "FILE=y":
    128 136   api.set_write_file(True)
    129 137   elif cmd == "FILE=n":
    skipped 8 lines
  • ■ ■ ■ ■ ■
    src/Osintgram.py
    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 + 
Please wait...
Page is in error, reload to recover