Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
deathsec
GitHub Repository: deathsec/instagram-py
Path: blob/master/InstagramPy/InstagramPySession.py
197 views
1
# The MIT License.
2
# Copyright (C) 2017 The Future Shell , DeathSec.
3
#
4
# @filename : InstagramPySession.py
5
# @description : creates a new session , checks for configuration and gets critical data
6
# , loads save and saves data too.
7
import json
8
import os
9
import uuid
10
import hashlib
11
import requests
12
from stem import Signal
13
from stem.control import Controller
14
15
DEFAULT_PATH = "{}/".format(os.path.expanduser('~'))
16
17
18
class InstagramPySession:
19
'''
20
__init__:
21
- loads configuration from specified file.
22
- gets the perfect place for the save file.
23
- sets class variables for later use.
24
'''
25
26
magic_cookie = None
27
api_url = None
28
user_agent = None
29
ig_sig_key = None
30
ig_sig_version = None
31
tor_proxy = None
32
tor_controller = None
33
save_data = None
34
dump_data = None
35
current_save = None
36
username = ''
37
password = ''
38
password_list = None
39
password_list_md5_sum = None
40
password_list_buffer = None
41
password_list_length = 0
42
eopl = False
43
current_line = 1
44
ip = None
45
cli = None
46
bot = requests.Session()
47
48
def __init__(self, username, password_list, configuration, save_location, cli):
49
50
self.username = username
51
self.cli = cli
52
53
if not os.path.isfile(password_list):
54
self.cli.ReportError(
55
"password list not found at {}.".format(password_list))
56
self.password_list = password_list
57
'''
58
Note: Always open password list with errors ignored because all password list
59
mostly has a wrong encoding or the users pc does not support it!
60
'''
61
self.password_list_buffer = open(
62
password_list, encoding='utf-8', errors='ignore')
63
self.password_list_md5_sum = str(
64
self.md5sum(open(password_list, "rb")).hexdigest())
65
66
with open(password_list, encoding='utf-8', errors='ignore') as f:
67
for line in f:
68
self.password_list_length += 1
69
70
if configuration == DEFAULT_PATH:
71
configuration = "{}instapy-config.json".format(DEFAULT_PATH)
72
if save_location == DEFAULT_PATH:
73
save_location = "{}.instagram-py/".format(DEFAULT_PATH)
74
75
dump_location = "{}dump.json".format(save_location)
76
77
if not os.path.isfile(configuration):
78
self.cli.ReportError(
79
"configuration file not found at {}".format(configuration))
80
else:
81
try:
82
with open(configuration, "r") as fp:
83
configuration = json.load(fp)
84
except Exception as err:
85
self.cli.ReportError(
86
"invalid configuration file at {}".format(configuraion))
87
88
self.api_url = configuration['api-url']
89
self.user_agent = configuration['user-agent']
90
self.ig_sig_key = configuration['ig-sig-key']
91
self.ig_sig_version = configuration['ig-sig-version']
92
self.tor_proxy = "{}://{}:{}".format(
93
configuration['tor']['protocol'], configuration['tor']['server'], configuration['tor']['port'])
94
if not configuration['tor']['control']['password'] == "":
95
self.OpenTorController(
96
configuration['tor']['control']['port'], configuration['tor']['control']['password'])
97
else:
98
self.OpenTorController(
99
configuration['tor']['control']['port'], None)
100
101
self.bot.proxies = {
102
# tor socks proxy!
103
"https": self.tor_proxy,
104
"http": self.tor_proxy
105
}
106
107
# build headers
108
109
self.bot.headers.update(
110
{
111
'Connection': 'close', # make sure requests closes the sockets instead of keep-alive!
112
'Accept': '*/*',
113
'Content-type': 'application/x-www-form-urlencoded; charset=UTF-8',
114
'Cookie2': '$Version=1',
115
'Accept-Language': 'en-US',
116
'User-Agent': self.user_agent
117
}
118
)
119
120
'''
121
Note: https://icanhazip.com is a free domain to get your current tor ip
122
this is not a dangerous website for sure , thank you @majorhayden
123
'''
124
try:
125
self.ip = self.bot.get(
126
'https://icanhazip.com').content.rstrip().decode()
127
except KeyboardInterrupt:
128
self.cli.ReportError("process aborted by the user")
129
except (BaseException, Exception) as err:
130
self.cli.ReportError(
131
"Connection to host failed , check your connection and tor configuration.")
132
133
if not os.path.exists(save_location):
134
try:
135
os.mkdir(save_location)
136
except (BaseException, Exception) as err:
137
self.cli.ReportError(err)
138
139
self.save_data = save_location
140
else:
141
self.save_data = save_location
142
143
self.dump_data = dump_location
144
145
try:
146
self.bot.get(
147
"{}si/fetch_headers/?challenge_type=signup&guid={}".format(
148
self.api_url, str(uuid.uuid4()).replace('-', ''))
149
)
150
self.magic_cookie = self.bot.cookies['csrftoken']
151
except KeyboardInterrupt:
152
self.cli.ReportError(
153
"cannot get the magic cookie , aborted by the user")
154
except (BaseException, Exception) as err:
155
self.cli.ReportError(err)
156
157
'''
158
ReadSaveFile()
159
- Checks if we have located the save file
160
- if not creates one
161
- opens the save file and load it as json data
162
- check if the user uses the same password list file for the same user
163
- set the current password pointer to the given data
164
'''
165
166
def ReadSaveFile(self, isResume):
167
if self.current_save == None:
168
self.CreateSaveFile(isResume)
169
SaveFile = json.load(open(self.current_save, 'r'))
170
self.current_line = SaveFile['line-count']
171
if self.password_list_md5_sum == SaveFile['password-file-md5'] and self.username == SaveFile['username']:
172
c_line = 1
173
for line in self.password_list_buffer:
174
self.password = str(line).rstrip()
175
if c_line == self.current_line:
176
break
177
c_line += 1
178
return True
179
180
'''
181
UpdateSaveFile()
182
- check if we have created a save file
183
- if yes , rewrite the the save file with the current session!
184
'''
185
186
def UpdateSaveFile(self):
187
if not self.current_save == None:
188
updatefile = open(self.current_save, 'w')
189
json.dump(
190
{
191
"username": str(self.username),
192
"password-file-md5": str(self.password_list_md5_sum),
193
"line-count": self.current_line
194
}, updatefile)
195
updatefile.close()
196
197
'''
198
CreateSaveFile()
199
- checks if we have not openned any save file but know the save location.
200
- if yes , creates with default settings to the location.
201
'''
202
203
def CreateSaveFile(self, isResume):
204
if self.current_save == None and not self.save_data == None:
205
save = '{}{}.dat'.format(self.save_data, hashlib.sha224(
206
self.username.encode('utf-8')).hexdigest())
207
self.current_save = save
208
if not os.path.isfile(save):
209
self.UpdateSaveFile()
210
else:
211
if not isResume:
212
self.UpdateSaveFile()
213
214
def ReadDumpFile(self, username):
215
if not self.dump_data == None:
216
if not os.path.isfile(self.dump_data):
217
return None
218
json_dump = json.load(open(self.dump_data, 'r'))
219
required_info = None
220
221
try:
222
required_info = json_dump[username]
223
except KeyError:
224
pass
225
226
return required_info
227
228
def WriteDumpFile(self, info):
229
if not self.dump_data == None:
230
json_dump = {}
231
if os.path.isfile(self.dump_data):
232
json_dump = json.load(open(self.dump_data, 'r'))
233
json_dump[info['id']] = info
234
json.dump(json_dump, open(self.dump_data, 'w'))
235
return True
236
237
'''
238
CurrentPassword()
239
- returns the current password pointed to the password list
240
'''
241
242
def CurrentPassword(self):
243
return self.password
244
245
'''
246
NextPassword()
247
- increaments and sets the next password as our current password
248
'''
249
250
def NextPassword(self):
251
if not self.current_line > self.password_list_length:
252
for line in self.password_list_buffer:
253
self.password = str(line.rstrip())
254
break
255
self.current_line += 1
256
else:
257
self.eopl = True
258
259
'''
260
GetUsername()
261
- returns current session username
262
'''
263
264
def GetUsername(self):
265
return self.username
266
267
'''
268
md5sum( FILE POINTER , BLOCK SIZE)
269
- opens large files from FILE POINTER
270
- calculates md5 with BLOCK SIZE with respect to FILE POINTER
271
- finalizes and returns a hashlib object!
272
'''
273
274
def md5sum(self, fp, block_size=2**20):
275
md5 = hashlib.md5()
276
while True:
277
data = fp.read(block_size)
278
if not data:
279
break
280
md5.update(data)
281
return md5
282
283
'''
284
ChangeIPAddress()
285
- stem <-> Signal
286
- Changes Tor Identity with the controller!
287
'''
288
289
def ChangeIPAddress(self):
290
if not self.tor_controller == None:
291
# signal tor to change ip
292
self.tor_controller.signal(Signal.NEWNYM)
293
self.ip = self.bot.get(
294
'https://icanhazip.com').content.rstrip().decode()
295
return True
296
return False
297
298
'''
299
OpenTorController(PORT , PASSWORD)
300
- Creates a fresh tor controller instance to the session
301
'''
302
303
def OpenTorController(self, port, password):
304
try:
305
self.tor_controller = Controller.from_port(port=int(port))
306
if password == None:
307
self.tor_controller.authenticate()
308
else:
309
self.tor_controller.authenticate(password=password)
310
except Exception as err:
311
self.cli.ReportError(
312
"Tor configuration invalid or server down :: {}".format(err))
313
314