| skipped 1 lines |
2 | 2 | | import json |
3 | 3 | | import sys |
4 | 4 | | import urllib |
| 5 | + | import os |
| 6 | + | import codecs |
5 | 7 | | |
6 | 8 | | from geopy.geocoders import Nominatim |
7 | 9 | | from instagram_private_api import Client as AppClient |
| 10 | + | from instagram_private_api import ClientCookieExpiredError, ClientLoginRequiredError, ClientError |
| 11 | + | |
8 | 12 | | from prettytable import PrettyTable |
9 | 13 | | |
10 | 14 | | from src import printcolors as pc |
| skipped 14 lines |
25 | 29 | | u = self.__getUsername__() |
26 | 30 | | p = self.__getPassword__() |
27 | 31 | | print("\nAttempt to login...") |
28 | | - | self.api = AppClient(auto_patch=True, authenticate=True, username=u, password=p) |
| 32 | + | self.login(u, p) |
29 | 33 | | self.setTarget(target) |
30 | 34 | | self.writeFile = is_file |
31 | 35 | | self.jsonDump = is_json |
| skipped 56 lines |
88 | 92 | | def __printTargetBanner__(self): |
89 | 93 | | pc.printout("\nLogged as ", pc.GREEN) |
90 | 94 | | 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) |
93 | 96 | | 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) |
95 | 100 | | print('\n') |
96 | 101 | | |
97 | 102 | | def change_target(self): |
| skipped 142 lines |
240 | 245 | | |
241 | 246 | | for post in data: |
242 | 247 | | comments_counter += post['comment_count'] |
| 248 | + | posts += 1 |
243 | 249 | | |
244 | 250 | | if self.writeFile: |
245 | 251 | | file_name = "output/" + self.target + "_comments.txt" |
| skipped 242 lines |
488 | 494 | | |
489 | 495 | | for post in data: |
490 | 496 | | like_counter += post['like_count'] |
| 497 | + | posts += 1 |
491 | 498 | | |
492 | 499 | | if self.writeFile: |
493 | 500 | | file_name = "output/" + self.target + "_likes.txt" |
| skipped 414 lines |
908 | 915 | | |
909 | 916 | | self.jsonDump = flag |
910 | 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)) |
| 971 | + | |