Skip to content

Commit

Permalink
Merge pull request #34 from Datalux/development
Browse files Browse the repository at this point in the history
v. 0.7
  • Loading branch information
Datalux authored Aug 26, 2020
2 parents ef7da43 + 0515130 commit c80f523
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 8 deletions.
13 changes: 13 additions & 0 deletions changelog.md → CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,18 @@
# Changelog

## [0.7](https://github.com/Datalux/Osintgram/releases/tag/0.7)

**Enhancements**
- banner now show target ID (#30)
- persistent login (#33)
- error handler (85e390b)
- added CTRL+C handler (c2c3c3e)

**Bug fixes**
- fix likes and comments posts counter bug (44b7534)



## [0.6](https://github.com/Datalux/Osintgram/releases/tag/0.6)

**Enhancements**
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[![](https://img.shields.io/badge/version-0.6-green)](https://github.com/Datalux/Osintgram/releases/tag/0.6)
[![](https://img.shields.io/badge/version-0.7-green)](https://github.com/Datalux/Osintgram/releases/tag/0.7)
[![](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)

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

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

## Tools
<p align="center">
Expand Down
10 changes: 9 additions & 1 deletion main.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import argparse
from src import printcolors as pc
import sys
import signal


def printlogo():
Expand All @@ -15,7 +16,7 @@ def printlogo():
pc.printout("\_______ /____ >__|___| /__| \___ /|__| (____ /__|_| /\n", pc.YELLOW)
pc.printout(" \/ \/ \/ /_____/ \/ \/ \n", pc.YELLOW)
print('\n')
pc.printout("Version 0.6 - Developed by Giuseppe Criscione - 2019\n\n", pc.YELLOW)
pc.printout("Version 0.7 - 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 '<target username>_<command>.txt (deafult is disabled)'\n")
pc.printout("Type 'FILE=n' to disable saving to files'\n")
Expand Down Expand Up @@ -63,6 +64,13 @@ def cmdlist():
print("Get a list of user who commented target's photos")


def signal_handler(sig, frame):
pc.printout("\nGoodbye!\n", pc.RED)
sys.exit(0)


signal.signal(signal.SIGINT, signal_handler)

printlogo()

parser = argparse.ArgumentParser(description='Osintgram is a OSINT tool on Instagram. It offers an interactive shell '
Expand Down
69 changes: 65 additions & 4 deletions src/Osintgram.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,13 @@
import json
import sys
import urllib
import os
import codecs

from geopy.geocoders import Nominatim
from instagram_private_api import Client as AppClient
from instagram_private_api import ClientCookieExpiredError, ClientLoginRequiredError, ClientError

from prettytable import PrettyTable

from src import printcolors as pc
Expand All @@ -25,7 +29,7 @@ def __init__(self, target, is_file, is_json):
u = self.__getUsername__()
p = self.__getPassword__()
print("\nAttempt to login...")
self.api = AppClient(auto_patch=True, authenticate=True, username=u, password=p)
self.login(u, p)
self.setTarget(target)
self.writeFile = is_file
self.jsonDump = is_json
Expand Down Expand Up @@ -88,10 +92,11 @@ def __get_comments__(self, media_id):
def __printTargetBanner__(self):
pc.printout("\nLogged as ", pc.GREEN)
pc.printout(self.api.username, pc.CYAN)
pc.printout(" (" + str(self.api.authenticated_user_id) + ") ")
pc.printout("target: ", pc.GREEN)
pc.printout(". Target: ", pc.GREEN)
pc.printout(str(self.target), pc.CYAN)
pc.printout(" (private: " + str(self.is_private) + ")")
pc.printout(" [" + str(self.target_id) + "] ")
if self.is_private:
pc.printout("[PRIVATE PROFILE]", pc.RED)
print('\n')

def change_target(self):
Expand Down Expand Up @@ -240,6 +245,7 @@ def get_total_comments(self):

for post in data:
comments_counter += post['comment_count']
posts += 1

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

for post in data:
like_counter += post['like_count']
posts += 1

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

self.jsonDump = flag

def login(self, u, p):
try:
settings_file = "config/settings.json"
if not os.path.isfile(settings_file):
# settings file does not exist
print('Unable to find file: {0!s}'.format(settings_file))

# login new
self.api = AppClient(auto_patch=True, authenticate=True, username=u, password=p,
on_login=lambda x: self.onlogin_callback(x, settings_file))

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))

# reuse auth settings
self.api = AppClient(
username=u, password=p,
settings=cached_settings,
on_login=lambda x: self.onlogin_callback(x, settings_file))

except (ClientCookieExpiredError, ClientLoginRequiredError) as e:
print('ClientCookieExpiredError/ClientLoginRequiredError: {0!s}'.format(e))

# Login expired
# Do relogin but use default ua, keys and such
self.api = AppClient(auto_patch=True, authenticate=True, username=u, password=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)
error = json.loads(e.error_response)
pc.printout(error['message'], pc.RED)
pc.printout("\n")
exit(9)

def to_json(self, python_object):
if isinstance(python_object, bytes):
return {'__class__': 'bytes',
'__value__': codecs.encode(python_object, 'base64').decode()}
raise TypeError(repr(python_object) + ' is not JSON serializable')

def from_json(self, json_object):
if '__class__' in json_object and json_object['__class__'] == 'bytes':
return codecs.decode(json_object['__value__'].encode(), 'base64')
return json_object

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))

0 comments on commit c80f523

Please sign in to comment.