Skip to content

Commit c80f523

Browse files
authored
Merge pull request #34 from Datalux/development
v. 0.7
2 parents ef7da43 + 0515130 commit c80f523

File tree

4 files changed

+90
-8
lines changed

4 files changed

+90
-8
lines changed

changelog.md renamed to CHANGELOG.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,18 @@
11
# Changelog
22

3+
## [0.7](https://github.com/Datalux/Osintgram/releases/tag/0.7)
4+
5+
**Enhancements**
6+
- banner now show target ID (#30)
7+
- persistent login (#33)
8+
- error handler (85e390b)
9+
- added CTRL+C handler (c2c3c3e)
10+
11+
**Bug fixes**
12+
- fix likes and comments posts counter bug (44b7534)
13+
14+
15+
316
## [0.6](https://github.com/Datalux/Osintgram/releases/tag/0.6)
417

518
**Enhancements**

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
[![](https://img.shields.io/badge/version-0.6-green)](https://github.com/Datalux/Osintgram/releases/tag/0.6)
1+
[![](https://img.shields.io/badge/version-0.7-green)](https://github.com/Datalux/Osintgram/releases/tag/0.7)
22
[![](https://img.shields.io/badge/license-GPLv3-blue)](https://img.shields.io/badge/license-GPLv3-blue)
33
[![](https://img.shields.io/badge/language-Python3-red)](https://img.shields.io/badge/language-Python3-red)
44

@@ -30,8 +30,8 @@ Osintgram offers an interactive shell to perform analysis on Instagram account o
3030
```
3131
You can find detailed commands usage [here](commands.md).
3232

33-
[**Latest version**](https://github.com/Datalux/Osintgram/releases/tag/0.6) |
34-
[CHANGELOG](changelog.md)
33+
[**Latest version**](https://github.com/Datalux/Osintgram/releases/tag/0.7) |
34+
[CHANGELOG](CHANGELOG.md)
3535

3636
## Tools
3737
<p align="center">

main.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import argparse
66
from src import printcolors as pc
77
import sys
8+
import signal
89

910

1011
def printlogo():
@@ -15,7 +16,7 @@ def printlogo():
1516
pc.printout("\_______ /____ >__|___| /__| \___ /|__| (____ /__|_| /\n", pc.YELLOW)
1617
pc.printout(" \/ \/ \/ /_____/ \/ \/ \n", pc.YELLOW)
1718
print('\n')
18-
pc.printout("Version 0.6 - Developed by Giuseppe Criscione - 2019\n\n", pc.YELLOW)
19+
pc.printout("Version 0.7 - Developed by Giuseppe Criscione - 2019\n\n", pc.YELLOW)
1920
pc.printout("Type 'list' to show all allowed commands\n")
2021
pc.printout("Type 'FILE=y' to save results to files like '<target username>_<command>.txt (deafult is disabled)'\n")
2122
pc.printout("Type 'FILE=n' to disable saving to files'\n")
@@ -63,6 +64,13 @@ def cmdlist():
6364
print("Get a list of user who commented target's photos")
6465

6566

67+
def signal_handler(sig, frame):
68+
pc.printout("\nGoodbye!\n", pc.RED)
69+
sys.exit(0)
70+
71+
72+
signal.signal(signal.SIGINT, signal_handler)
73+
6674
printlogo()
6775

6876
parser = argparse.ArgumentParser(description='Osintgram is a OSINT tool on Instagram. It offers an interactive shell '

src/Osintgram.py

Lines changed: 65 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,13 @@
22
import json
33
import sys
44
import urllib
5+
import os
6+
import codecs
57

68
from geopy.geocoders import Nominatim
79
from instagram_private_api import Client as AppClient
10+
from instagram_private_api import ClientCookieExpiredError, ClientLoginRequiredError, ClientError
11+
812
from prettytable import PrettyTable
913

1014
from src import printcolors as pc
@@ -25,7 +29,7 @@ def __init__(self, target, is_file, is_json):
2529
u = self.__getUsername__()
2630
p = self.__getPassword__()
2731
print("\nAttempt to login...")
28-
self.api = AppClient(auto_patch=True, authenticate=True, username=u, password=p)
32+
self.login(u, p)
2933
self.setTarget(target)
3034
self.writeFile = is_file
3135
self.jsonDump = is_json
@@ -88,10 +92,11 @@ def __get_comments__(self, media_id):
8892
def __printTargetBanner__(self):
8993
pc.printout("\nLogged as ", pc.GREEN)
9094
pc.printout(self.api.username, pc.CYAN)
91-
pc.printout(" (" + str(self.api.authenticated_user_id) + ") ")
92-
pc.printout("target: ", pc.GREEN)
95+
pc.printout(". Target: ", pc.GREEN)
9396
pc.printout(str(self.target), pc.CYAN)
94-
pc.printout(" (private: " + str(self.is_private) + ")")
97+
pc.printout(" [" + str(self.target_id) + "] ")
98+
if self.is_private:
99+
pc.printout("[PRIVATE PROFILE]", pc.RED)
95100
print('\n')
96101

97102
def change_target(self):
@@ -240,6 +245,7 @@ def get_total_comments(self):
240245

241246
for post in data:
242247
comments_counter += post['comment_count']
248+
posts += 1
243249

244250
if self.writeFile:
245251
file_name = "output/" + self.target + "_comments.txt"
@@ -488,6 +494,7 @@ def get_total_likes(self):
488494

489495
for post in data:
490496
like_counter += post['like_count']
497+
posts += 1
491498

492499
if self.writeFile:
493500
file_name = "output/" + self.target + "_likes.txt"
@@ -907,3 +914,57 @@ def set_json_dump(self, flag):
907914
pc.printout("\n")
908915

909916
self.jsonDump = flag
917+
918+
def login(self, u, p):
919+
try:
920+
settings_file = "config/settings.json"
921+
if not os.path.isfile(settings_file):
922+
# settings file does not exist
923+
print('Unable to find file: {0!s}'.format(settings_file))
924+
925+
# login new
926+
self.api = AppClient(auto_patch=True, authenticate=True, username=u, password=p,
927+
on_login=lambda x: self.onlogin_callback(x, settings_file))
928+
929+
else:
930+
with open(settings_file) as file_data:
931+
cached_settings = json.load(file_data, object_hook=self.from_json)
932+
#print('Reusing settings: {0!s}'.format(settings_file))
933+
934+
# reuse auth settings
935+
self.api = AppClient(
936+
username=u, password=p,
937+
settings=cached_settings,
938+
on_login=lambda x: self.onlogin_callback(x, settings_file))
939+
940+
except (ClientCookieExpiredError, ClientLoginRequiredError) as e:
941+
print('ClientCookieExpiredError/ClientLoginRequiredError: {0!s}'.format(e))
942+
943+
# Login expired
944+
# Do relogin but use default ua, keys and such
945+
self.api = AppClient(auto_patch=True, authenticate=True, username=u, password=p,
946+
on_login=lambda x: self.onlogin_callback(x, settings_file))
947+
948+
except ClientError as e:
949+
#pc.printout('ClientError {0!s} (Code: {1:d}, Response: {2!s})'.format(e.msg, e.code, e.error_response), pc.RED)
950+
error = json.loads(e.error_response)
951+
pc.printout(error['message'], pc.RED)
952+
pc.printout("\n")
953+
exit(9)
954+
955+
def to_json(self, python_object):
956+
if isinstance(python_object, bytes):
957+
return {'__class__': 'bytes',
958+
'__value__': codecs.encode(python_object, 'base64').decode()}
959+
raise TypeError(repr(python_object) + ' is not JSON serializable')
960+
961+
def from_json(self, json_object):
962+
if '__class__' in json_object and json_object['__class__'] == 'bytes':
963+
return codecs.decode(json_object['__value__'].encode(), 'base64')
964+
return json_object
965+
966+
def onlogin_callback(self, api, new_settings_file):
967+
cache_settings = api.settings
968+
with open(new_settings_file, 'w') as outfile:
969+
json.dump(cache_settings, outfile, default=self.to_json)
970+
#print('SAVED: {0!s}'.format(new_settings_file))

0 commit comments

Comments
 (0)