From 828f634bd36fd50ecedee1c34cb364a7eb062662 Mon Sep 17 00:00:00 2001 From: Giuseppe Criscione Date: Mon, 31 Aug 2020 09:40:20 +0200 Subject: [PATCH 01/13] Update CHANGELOG.md --- doc/CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/CHANGELOG.md b/doc/CHANGELOG.md index fb0cfff4..59e3bff1 100644 --- a/doc/CHANGELOG.md +++ b/doc/CHANGELOG.md @@ -4,13 +4,14 @@ **Enhancements** - Added `wtagged` command (#38) +- Added `fwersemail` command (#40) - Access private profiles if you following targets (#37) - Added more info in `info` command (#36) + **Bug fixes** - Minor bug fix in `addrs` commands (9b9086a) - ## [0.7](https://github.com/Datalux/Osintgram/releases/tag/0.7) **Enhancements** From 31f4f949cdf6c530d5945902233b9c124020f7f3 Mon Sep 17 00:00:00 2001 From: Datalux Date: Tue, 1 Sep 2020 10:41:41 +0200 Subject: [PATCH 02/13] feat: added follow request options --- src/Osintgram.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Osintgram.py b/src/Osintgram.py index a870dcd6..95e266c9 100644 --- a/src/Osintgram.py +++ b/src/Osintgram.py @@ -1054,6 +1054,11 @@ def check_following(self): def check_private_profile(self): if self.is_private and not self.following: pc.printout("Impossible to execute command: user has private profile\n", pc.RED) + send = input("Do you want send a follow request? [Y/N]: ") + if send.lower() == "y": + self.api.friendships_create(self.target_id) + print("Sent a follow request to target. Use this command after target accepting the request.") + return True return False From 9966dde2754cae0946944b269ae4ee591b0e7ddb Mon Sep 17 00:00:00 2001 From: Datalux Date: Thu, 3 Sep 2020 11:56:12 +0200 Subject: [PATCH 03/13] fix: fix issue #46 --- src/Osintgram.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Osintgram.py b/src/Osintgram.py index a870dcd6..5efcd775 100644 --- a/src/Osintgram.py +++ b/src/Osintgram.py @@ -949,7 +949,7 @@ def get_people_tagged_by_user(self): def get_user(self, username): try: content = urllib.request.urlopen("https://www.instagram.com/" + username + "/?__a=1") - data = json.load(content) + data = json.load(content.decode('utf-8')) if self.writeFile: file_name = "output/" + self.target + "_user_id.txt" file = open(file_name, "w") From f9c5f730ec9dd015dceb0b127b1e4742b75cdfe5 Mon Sep 17 00:00:00 2001 From: Datalux Date: Thu, 3 Sep 2020 12:10:28 +0200 Subject: [PATCH 04/13] fix(issue #46): using requests instead urllib --- src/Osintgram.py | 187 ++++++++++++++++++++++++----------------------- 1 file changed, 96 insertions(+), 91 deletions(-) diff --git a/src/Osintgram.py b/src/Osintgram.py index 5efcd775..79dafaa5 100644 --- a/src/Osintgram.py +++ b/src/Osintgram.py @@ -5,6 +5,8 @@ import os import codecs +import requests + from geopy.geocoders import Nominatim from instagram_private_api import Client as AppClient from instagram_private_api import ClientCookieExpiredError, ClientLoginRequiredError, ClientError @@ -440,61 +442,61 @@ def get_hashtags(self): pc.printout("Sorry! No results found :-(\n", pc.RED) def get_user_info(self): - try: - content = urllib.request.urlopen("https://www.instagram.com/" + str(self.target) + "/?__a=1") - data = json.load(content) - data = data['graphql']['user'] + content = requests.get("https://www.instagram.com/" + str(self.target) + "/?__a=1") + + if content.status_code == 404: + print("Oops... " + str(self.target) + " non exist, please enter a valid username.") + sys.exit(2) + + data = content.json() + data = data['graphql']['user'] + + pc.printout("[ID] ", pc.GREEN) + pc.printout(str(data['id']) + '\n') + pc.printout("[FULL NAME] ", pc.RED) + pc.printout(str(data['full_name']) + '\n') + pc.printout("[BIOGRAPHY] ", pc.CYAN) + pc.printout(str(data['biography']) + '\n') + pc.printout("[FOLLOWED] ", pc.BLUE) + pc.printout(str(data['edge_followed_by']['count']) + '\n') + pc.printout("[FOLLOW] ", pc.GREEN) + pc.printout(str(data['edge_follow']['count']) + '\n') + pc.printout("[BUSINESS ACCOUNT] ", pc.RED) + pc.printout(str(data['is_business_account']) + '\n') + if data['is_business_account']: + pc.printout("[BUSINESS CATEGORY] ") + pc.printout(str(data['business_category_name']) + '\n') + pc.printout("[VERIFIED ACCOUNT] ", pc.CYAN) + pc.printout(str(data['is_verified']) + '\n') + if data['business_email']: + pc.printout("[BUSINESS EMAIL] ", pc.BLUE) + pc.printout(str(data['business_email']) + '\n') + pc.printout("[HD PROFILE PIC] ", pc.GREEN) + pc.printout(str(data['profile_pic_url_hd']) + '\n') + if data['connected_fb_page']: + pc.printout("[FB PAGE] ", pc.RED) + pc.printout(str(data['business_email']) + '\n') - pc.printout("[ID] ", pc.GREEN) - pc.printout(str(data['id']) + '\n') - pc.printout("[FULL NAME] ", pc.RED) - pc.printout(str(data['full_name']) + '\n') - pc.printout("[BIOGRAPHY] ", pc.CYAN) - pc.printout(str(data['biography']) + '\n') - pc.printout("[FOLLOWED] ", pc.BLUE) - pc.printout(str(data['edge_followed_by']['count']) + '\n') - pc.printout("[FOLLOW] ", pc.GREEN) - pc.printout(str(data['edge_follow']['count']) + '\n') - pc.printout("[BUSINESS ACCOUNT] ", pc.RED) - pc.printout(str(data['is_business_account']) + '\n') - if data['is_business_account']: - pc.printout("[BUSINESS CATEGORY] ") - pc.printout(str(data['business_category_name']) + '\n') - pc.printout("[VERIFIED ACCOUNT] ", pc.CYAN) - pc.printout(str(data['is_verified']) + '\n') + if self.jsonDump: + user = { + 'id': data['id'], + 'full_name': data['full_name'], + 'biography': data['biography'], + 'edge_followed_by': data['edge_followed_by']['count'], + 'edge_follow': data['edge_follow']['count'], + 'is_business_account': data['is_business_account'], + 'is_verified': data['is_verified'], + 'profile_pic_url_hd': data['profile_pic_url_hd'] + } if data['business_email']: - pc.printout("[BUSINESS EMAIL] ", pc.BLUE) - pc.printout(str(data['business_email']) + '\n') - pc.printout("[HD PROFILE PIC] ", pc.GREEN) - pc.printout(str(data['profile_pic_url_hd']) + '\n') + user['business_email'] = data['business_email'] if data['connected_fb_page']: - pc.printout("[FB PAGE] ", pc.RED) - pc.printout(str(data['business_email']) + '\n') - - if self.jsonDump: - user = { - 'id': data['id'], - 'full_name': data['full_name'], - 'biography': data['biography'], - 'edge_followed_by': data['edge_followed_by']['count'], - 'edge_follow': data['edge_follow']['count'], - 'is_business_account': data['is_business_account'], - 'is_verified': data['is_verified'], - 'profile_pic_url_hd': data['profile_pic_url_hd'] - } - if data['business_email']: - user['business_email'] = data['business_email'] - if data['connected_fb_page']: - user['connected_fb_page'] = data['connected_fb_page'] + user['connected_fb_page'] = data['connected_fb_page'] - json_file_name = "output/" + self.target + "_info.json" - with open(json_file_name, 'w') as f: - json.dump(user, f) + json_file_name = "output/" + self.target + "_info.json" + with open(json_file_name, 'w') as f: + json.dump(user, f) - except urllib.error.HTTPError as err: - if err.code == 404: - print("Oops... " + str(self.target) + " non exist, please enter a valid username.") - sys.exit(2) def get_total_likes(self): if self.check_private_profile(): @@ -707,8 +709,9 @@ def get_photo_description(self): if self.check_private_profile(): return - content = urllib.request.urlopen("https://www.instagram.com/" + str(self.target) + "/?__a=1") - data = json.load(content) + content = requests.get("https://www.instagram.com/" + str(self.target) + "/?__a=1") + data = content.json() + dd = data['graphql']['user']['edge_owner_to_timeline_media']['edges'] if len(dd) > 0: @@ -819,28 +822,28 @@ def get_user_photo(self): pc.printout("\nWoohoo! We downloaded " + str(counter) + " photos (saved in output/ folder) \n", pc.GREEN) def get_user_propic(self): - try: - content = urllib.request.urlopen("https://www.instagram.com/" + str(self.target) + "/?__a=1") + content = requests.get("https://www.instagram.com/" + str(self.target) + "/?__a=1") - data = json.load(content) + if content.status_code == 404: + print("Oops... " + str(self.target) + " non exist, please enter a valid username.") + sys.exit(2) - uurl = data["graphql"]["user"] - if "profile_pic_url_hd" in uurl: - URL = data["graphql"]["user"]["profile_pic_url_hd"] - else: - URL = data["graphql"]["user"]["profile_pic_url"] + data = content.json() - if URL != "": - end = "output/" + self.target + "_propic.jpg" - urllib.request.urlretrieve(URL, end) - pc.printout("Target propic saved in output folder\n", pc.GREEN) + uurl = data["graphql"]["user"] + if "profile_pic_url_hd" in uurl: + URL = data["graphql"]["user"]["profile_pic_url_hd"] + else: + URL = data["graphql"]["user"]["profile_pic_url"] + + if URL != "": + end = "output/" + self.target + "_propic.jpg" + urllib.request.urlretrieve(URL, end) + pc.printout("Target propic saved in output folder\n", pc.GREEN) + + else: + pc.printout("Sorry! No results found :-(\n", pc.RED) - else: - pc.printout("Sorry! No results found :-(\n", pc.RED) - except urllib.error.HTTPError as err: - if err.code == 404: - print("Oops... " + str(self.target) + " non exist, please enter a valid username.") - sys.exit(2) def get_user_stories(self): if self.check_private_profile(): @@ -849,8 +852,10 @@ def get_user_stories(self): pc.printout("Searching for target stories...\n") endpoint = 'feed/user/{id!s}/story/'.format(**{'id': self.target_id}) - content = urllib.request.urlopen("https://www.instagram.com/" + endpoint) - data = json.load(content) + + content = requests.get("https://www.instagram.com/" + endpoint) + data = content.json() + counter = 0 if data['reel'] is not None: # no stories avaibile @@ -947,27 +952,26 @@ def get_people_tagged_by_user(self): pc.printout("Sorry! No results found :-(\n", pc.RED) def get_user(self, username): - try: - content = urllib.request.urlopen("https://www.instagram.com/" + username + "/?__a=1") - data = json.load(content.decode('utf-8')) - if self.writeFile: - file_name = "output/" + self.target + "_user_id.txt" - file = open(file_name, "w") - file.write(str(data['graphql']['user']['id'])) - file.close() + content = requests.get("https://www.instagram.com/" + username + "/?__a=1") - user = dict() - user['id'] = data['graphql']['user']['id'] - user['is_private'] = data['graphql']['user']['is_private'] + if content.status_code == 404: + print("Oops... " + str(self.target) + " non exist, please enter a valid username.") + sys.exit(2) - return user + data = content.json() - except urllib.error.HTTPError as err: - if err.code == 404: - print("Oops... " + username + " non exist, please enter a valid username.") - sys.exit(2) + if self.writeFile: + file_name = "output/" + self.target + "_user_id.txt" + file = open(file_name, "w") + file.write(str(data['graphql']['user']['id'])) + file.close() + + user = dict() + user['id'] = data['graphql']['user']['id'] + user['is_private'] = data['graphql']['user']['is_private'] + + return user - return None def set_write_file(self, flag): if flag: @@ -1079,8 +1083,9 @@ def get_fwersemail(self): results = [] for follow in followers: - req = urllib.request.urlopen("https://www.instagram.com/" + str(follow['username']) + "/?__a=1") - data = json.load(req)['graphql']['user'] + content = requests.get("https://www.instagram.com/" + str(follow['username']) + "/?__a=1") + data = content.json() + data = data['graphql']['user'] if data['business_email']: follow['email'] = data['business_email'] results.append(follow) From 3ccb4a3ca22d7c945df28176fe46d68456e0c37f Mon Sep 17 00:00:00 2001 From: Datalux Date: Sat, 5 Sep 2020 10:27:37 +0200 Subject: [PATCH 05/13] refactor: indent --- src/Osintgram.py | 46 +++++++++++++++++----------------------------- 1 file changed, 17 insertions(+), 29 deletions(-) diff --git a/src/Osintgram.py b/src/Osintgram.py index 110e9888..68c4ee0c 100644 --- a/src/Osintgram.py +++ b/src/Osintgram.py @@ -106,7 +106,6 @@ def __printTargetBanner__(self): else: pc.printout(" [NOT FOLLOWING]", pc.RED) - print('\n') def change_target(self): @@ -497,7 +496,6 @@ def get_user_info(self): with open(json_file_name, 'w') as f: json.dump(user, f) - def get_total_likes(self): if self.check_private_profile(): return @@ -660,19 +658,19 @@ def get_people_who_tagged(self): users = [] for post in posts: - if not any(u['id'] == post['user']['pk'] for u in users): - user = { - 'id': post['user']['pk'], - 'username': post['user']['username'], - 'full_name': post['user']['full_name'], - 'counter': 1 - } - users.append(user) - else: - for user in users: - if user['id'] == post['user']['pk']: - user['counter'] += 1 - break + if not any(u['id'] == post['user']['pk'] for u in users): + user = { + 'id': post['user']['pk'], + 'username': post['user']['username'], + 'full_name': post['user']['full_name'], + 'counter': 1 + } + users.append(user) + else: + for user in users: + if user['id'] == post['user']['pk']: + user['counter'] += 1 + break ssort = sorted(users, key=lambda value: value['counter'], reverse=True) @@ -844,7 +842,6 @@ def get_user_propic(self): else: pc.printout("Sorry! No results found :-(\n", pc.RED) - def get_user_stories(self): if self.check_private_profile(): return @@ -854,6 +851,7 @@ def get_user_stories(self): endpoint = 'feed/user/{id!s}/story/'.format(**{'id': self.target_id}) content = requests.get("https://www.instagram.com/" + endpoint) + print(content) data = content.json() counter = 0 @@ -972,7 +970,6 @@ def get_user(self, username): return user - def set_write_file(self, flag): if flag: pc.printout("Write to file: ") @@ -1011,7 +1008,7 @@ def login(self, u, p): else: with open(settings_file) as file_data: cached_settings = json.load(file_data, object_hook=self.from_json) - #print('Reusing settings: {0!s}'.format(settings_file)) + # print('Reusing settings: {0!s}'.format(settings_file)) # reuse auth settings self.api = AppClient( @@ -1028,7 +1025,7 @@ def login(self, u, p): on_login=lambda x: self.onlogin_callback(x, settings_file)) except ClientError as e: - #pc.printout('ClientError {0!s} (Code: {1:d}, Response: {2!s})'.format(e.msg, e.code, e.error_response), pc.RED) + # pc.printout('ClientError {0!s} (Code: {1:d}, Response: {2!s})'.format(e.msg, e.code, e.error_response), pc.RED) error = json.loads(e.error_response) pc.printout(error['message'], pc.RED) pc.printout("\n") @@ -1049,7 +1046,7 @@ def onlogin_callback(self, api, new_settings_file): cache_settings = api.settings with open(new_settings_file, 'w') as outfile: json.dump(cache_settings, outfile, default=self.to_json) - #print('SAVED: {0!s}'.format(new_settings_file)) + # print('SAVED: {0!s}'.format(new_settings_file)) def check_following(self): endpoint = 'users/{user_id!s}/full_detail_info/'.format(**{'user_id': self.target_id}) @@ -1123,12 +1120,3 @@ def get_fwersemail(self): print(t) else: pc.printout("Sorry! No results found :-(\n", pc.RED) - - - - - - - - - From 8816881e1283dad183f611163e43866d136dd916 Mon Sep 17 00:00:00 2001 From: Datalux Date: Sat, 5 Sep 2020 10:50:11 +0200 Subject: [PATCH 06/13] fix: stories bug --- src/Osintgram.py | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/src/Osintgram.py b/src/Osintgram.py index 68c4ee0c..f2cd332a 100644 --- a/src/Osintgram.py +++ b/src/Osintgram.py @@ -848,28 +848,23 @@ def get_user_stories(self): pc.printout("Searching for target stories...\n") - endpoint = 'feed/user/{id!s}/story/'.format(**{'id': self.target_id}) - - content = requests.get("https://www.instagram.com/" + endpoint) - print(content) - data = content.json() + data = self.api.user_reel_media(str(self.target_id)) counter = 0 - if data['reel'] is not None: # no stories avaibile - for i in data['reel']['items']: + if data['items'] is not None: # no stories avaibile + counter = data['media_count'] + for i in data['items']: story_id = i["id"] if i["media_type"] == 1: # it's a photo url = i['image_versions2']['candidates'][0]['url'] end = "output/" + self.target + "_" + story_id + ".jpg" urllib.request.urlretrieve(url, end) - counter += 1 elif i["media_type"] == 2: # it's a gif or video url = i['video_versions'][0]['url'] end = "output/" + self.target + "_" + story_id + ".mp4" urllib.request.urlretrieve(url, end) - counter += 1 if counter > 0: pc.printout(str(counter) + " target stories saved in output folder\n", pc.GREEN) From 7df664998db51fbe8fc68f7481d5f77cd8c45078 Mon Sep 17 00:00:00 2001 From: Datalux Date: Sat, 5 Sep 2020 11:11:21 +0200 Subject: [PATCH 07/13] feat: init command --- README.md | 3 ++- doc/COMMANDS.md | 6 +++++- main.py | 4 ++++ 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index af0379af..9648c1e9 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,8 @@ Osintgram offers an interactive shell to perform analysis on Instagram account o - comments Get total comments of target's posts - followers Get target followers - followings Get users followed by target -- fwersemail Get email of users followed by target +- fwersemail Get email of target followers +- fwingsemail Get email of users followed by target - hashtags Get hashtags used by target - info Get target info - likes Get total likes of target's posts diff --git a/doc/COMMANDS.md b/doc/COMMANDS.md index 55b42160..ccdae6ba 100644 --- a/doc/COMMANDS.md +++ b/doc/COMMANDS.md @@ -5,7 +5,8 @@ - comments Get total comments of target's posts - followers Get target followers - followings Get users followed by target -- fwersemail Get email of users followed by target +- fwersemail Get email of target followers +- fwingsemail Get email of users followed by target - hashtags Get hashtags used by target - info Get target info - likes Get total likes of target's posts @@ -48,6 +49,9 @@ Return a list with users followed by target with id, nickname and full name ### fwersemail Return a list of emails of target followers +### fwingsemail +Return a list of emails of user followed by target + ### hashtags Return a list with all hashtag used by target in his photos diff --git a/main.py b/main.py index 73b7d50b..fb0e268c 100644 --- a/main.py +++ b/main.py @@ -41,6 +41,8 @@ def cmdlist(): pc.printout("followings\t") print("Get users followed by target") pc.printout("fwersemail\t") + print("Get email of target followers") + pc.printout("fwingsemail\t") print("Get email of users followed by target") pc.printout("hashtags\t") print("Get hashtags used by target") @@ -108,6 +110,8 @@ def signal_handler(sig, frame): api.get_followings() elif cmd == 'fwersemail': api.get_fwersemail() + elif cmd == 'fwingsemail': + api.get_fwingsemail() elif cmd == "hashtags": api.get_hashtags() elif cmd == "info": From f94fd8a0727a9de29964fa93442703bf69feaa33 Mon Sep 17 00:00:00 2001 From: Datalux Date: Sat, 5 Sep 2020 11:15:33 +0200 Subject: [PATCH 08/13] feat: added command --- src/Osintgram.py | 62 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 60 insertions(+), 2 deletions(-) diff --git a/src/Osintgram.py b/src/Osintgram.py index f2cd332a..63211797 100644 --- a/src/Osintgram.py +++ b/src/Osintgram.py @@ -1101,14 +1101,72 @@ def get_fwersemail(self): t.add_row([str(node['id']), node['username'], node['full_name'], node['email']]) if self.writeFile: - file_name = "output/" + self.target + "_followers.txt" + file_name = "output/" + self.target + "_fwersemail.txt" file = open(file_name, "w") file.write(str(t)) file.close() if self.jsonDump: json_data['followers'] = results - json_file_name = "output/" + self.target + "_followers.json" + json_file_name = "output/" + self.target + "_fwersemail.json" + with open(json_file_name, 'w') as f: + json.dump(json_data, f) + + print(t) + else: + pc.printout("Sorry! No results found :-(\n", pc.RED) + + def get_fwingsemail(self): + if self.check_private_profile(): + return + + pc.printout("Searching for emails of users followed by target... this can take a few minutes\n") + + followings = [] + + rank_token = AppClient.generate_uuid() + data = self.api.user_following(str(self.target_id), rank_token=rank_token) + + for user in data['users']: + u = { + 'id': user['pk'], + 'username': user['username'], + 'full_name': user['full_name'] + } + followings.append(u) + + results = [] + + for follow in followings: + content = requests.get("https://www.instagram.com/" + str(follow['username']) + "/?__a=1") + data = content.json() + data = data['graphql']['user'] + if data['business_email']: + follow['email'] = data['business_email'] + results.append(follow) + + if len(results) > 0: + + t = PrettyTable(['ID', 'Username', 'Full Name', 'Email']) + t.align["ID"] = "l" + t.align["Username"] = "l" + t.align["Full Name"] = "l" + t.align["Email"] = "l" + + json_data = {} + + for node in results: + t.add_row([str(node['id']), node['username'], node['full_name'], node['email']]) + + if self.writeFile: + file_name = "output/" + self.target + "_fwingsemail.txt" + file = open(file_name, "w") + file.write(str(t)) + file.close() + + if self.jsonDump: + json_data['followers'] = results + json_file_name = "output/" + self.target + "_fwingsemail.json" with open(json_file_name, 'w') as f: json.dump(json_data, f) From e242c54dbb475545cbb5e663cd423639d6c650c5 Mon Sep 17 00:00:00 2001 From: Datalux Date: Sat, 5 Sep 2020 11:17:07 +0200 Subject: [PATCH 09/13] fix: typo --- src/Osintgram.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Osintgram.py b/src/Osintgram.py index 63211797..8eb6fb75 100644 --- a/src/Osintgram.py +++ b/src/Osintgram.py @@ -1107,7 +1107,7 @@ def get_fwersemail(self): file.close() if self.jsonDump: - json_data['followers'] = results + json_data['followers_email'] = results json_file_name = "output/" + self.target + "_fwersemail.json" with open(json_file_name, 'w') as f: json.dump(json_data, f) @@ -1165,7 +1165,7 @@ def get_fwingsemail(self): file.close() if self.jsonDump: - json_data['followers'] = results + json_data['followings_email'] = results json_file_name = "output/" + self.target + "_fwingsemail.json" with open(json_file_name, 'w') as f: json.dump(json_data, f) From 301bda683d9098b49ff57f3b47c6835f6dd78053 Mon Sep 17 00:00:00 2001 From: Datalux Date: Sat, 5 Sep 2020 11:20:33 +0200 Subject: [PATCH 10/13] chore: update version --- main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.py b/main.py index fb0e268c..b3d9f7e0 100644 --- a/main.py +++ b/main.py @@ -16,7 +16,7 @@ def printlogo(): pc.printout("\_______ /____ >__|___| /__| \___ /|__| (____ /__|_| /\n", pc.YELLOW) pc.printout(" \/ \/ \/ /_____/ \/ \/ \n", pc.YELLOW) print('\n') - pc.printout("Version 0.8 - Developed by Giuseppe Criscione - 2019\n\n", pc.YELLOW) + pc.printout("Version 0.9 - Developed by Giuseppe Criscione - 2019\n\n", pc.YELLOW) pc.printout("Type 'list' to show all allowed commands\n") pc.printout("Type 'FILE=y' to save results to files like '_.txt (deafult is disabled)'\n") pc.printout("Type 'FILE=n' to disable saving to files'\n") From 07e0fe83fd189209e4a96c4794326e9aef0ff65f Mon Sep 17 00:00:00 2001 From: Datalux Date: Sat, 5 Sep 2020 11:34:51 +0200 Subject: [PATCH 11/13] feat: added autocomplete with TAB --- main.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/main.py b/main.py index b3d9f7e0..67cf3ba7 100644 --- a/main.py +++ b/main.py @@ -6,6 +6,12 @@ from src import printcolors as pc import sys import signal +import readline + +commands = ["quit", "exit", "list", "help", "addrs", "captions", "comments", "followers", + "followings", "fwersemail", "fwingsemail", "hashtags", "info", "likes", + "mediatype", "photodes", "photos", "propic", "stories", "tagged", "target", + "wcommented", "wtagged"] def printlogo(): @@ -75,7 +81,17 @@ def signal_handler(sig, frame): sys.exit(0) +def completer(text, state): + options = [i for i in commands if i.startswith(text)] + if state < len(options): + return options[state] + else: + return None + + signal.signal(signal.SIGINT, signal_handler) +readline.parse_and_bind("tab: complete") +readline.set_completer(completer) printlogo() From 1160825515f6244b90b7a936a3d95a42b0694182 Mon Sep 17 00:00:00 2001 From: Datalux Date: Sat, 5 Sep 2020 11:45:34 +0200 Subject: [PATCH 12/13] chore: update requirements --- requirements.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index e075b811..62e51139 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,5 @@ requests==2.24.0 requests-toolbelt==0.9.1 -moviepy==0.2.2.11 geopy==1.11 prettytable==0.7.2 instagram-private-api==1.6.0 \ No newline at end of file From fb069af5965dca1ac1a4d55554caf5715babf3e8 Mon Sep 17 00:00:00 2001 From: Datalux Date: Tue, 8 Sep 2020 11:03:44 +0200 Subject: [PATCH 13/13] chore: update version in doc --- README.md | 4 ++-- doc/CHANGELOG.md | 11 +++++++++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 9648c1e9..1f89a5de 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -[![](https://img.shields.io/badge/version-0.8-green)](https://github.com/Datalux/Osintgram/releases/tag/0.8) +[![](https://img.shields.io/badge/version-0.9-green)](https://github.com/Datalux/Osintgram/releases/tag/0.9) [![](https://img.shields.io/badge/license-GPLv3-blue)](https://img.shields.io/badge/license-GPLv3-blue) [![](https://img.shields.io/badge/language-Python3-red)](https://img.shields.io/badge/language-Python3-red) @@ -32,7 +32,7 @@ Osintgram offers an interactive shell to perform analysis on Instagram account o ``` You can find detailed commands usage [here](doc/COMMANDS.md). -[**Latest version**](https://github.com/Datalux/Osintgram/releases/tag/0.8) | +[**Latest version**](https://github.com/Datalux/Osintgram/releases/tag/0.9) | [CHANGELOG](doc/CHANGELOG.md) ## Tools diff --git a/doc/CHANGELOG.md b/doc/CHANGELOG.md index 59e3bff1..4dcabd0f 100644 --- a/doc/CHANGELOG.md +++ b/doc/CHANGELOG.md @@ -1,5 +1,16 @@ # Changelog +## [0.9](https://github.com/Datalux/Osintgram/releases/tag/0.9) + +**Enhancements** +- Send a follow request if user not following target (#44) +- Added new `fwingsemail` command (#50) +- Added autocomplete with TAB (07e0fe8) + +**Bug fixes** +- Decoding error of response [bug #46] (f9c5f73) +- `stories` command not working (#49) + ## [0.8](https://github.com/Datalux/Osintgram/releases/tag/0.8) **Enhancements**