Total Complexity | 148 |
Total Lines | 1388 |
Duplicated Lines | 2.67 % |
Changes | 27 | ||
Bugs | 3 | Features | 2 |
Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
Complex classes like Instagram often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
1 | import json |
||
25 | class Instagram: |
||
26 | def __init__(self, username, password, debug=False, IGDataPath=None): |
||
27 | |||
28 | """ |
||
29 | Default class constructor. |
||
30 | :type username: str |
||
31 | :param username: Your Instagram username. |
||
32 | :type password: str |
||
33 | :param password: Your Instagram password. |
||
34 | :param debug: Debug on or off, False by default. |
||
35 | :param IGDataPath: Default folder to store data, you can change it. |
||
36 | """ |
||
37 | self.username = None # // Instagram username |
||
38 | self.password = None # // Instagram password |
||
39 | self.debug = None # // Debug |
||
40 | |||
41 | self.uuid = None # // UUID |
||
42 | self.device_id = None # // Device ID |
||
43 | self.username_id = None # // Username ID |
||
44 | self.token = None # // _csrftoken |
||
45 | self.isLoggedIn = False # // Session status |
||
46 | self.rank_token = None # // Rank token |
||
47 | self.IGDataPath = None # // Data storage path |
||
48 | self.customPath = False |
||
49 | self.http = None |
||
50 | self.settings = None |
||
51 | self.proxy = None # Full Proxy |
||
52 | self.proxyHost = None # Proxy Host and Port |
||
53 | self.proxyAuth = None # Proxy User and Pass |
||
54 | |||
55 | self.debug = debug |
||
56 | self.device_id = SignatureUtils.generateDeviceId(hashlib.md5(username + password)) |
||
57 | |||
58 | if IGDataPath is not None: |
||
59 | self.IGDataPath = IGDataPath |
||
60 | self.customPath = True |
||
61 | else: |
||
62 | self.IGDataPath = os.path.join( |
||
63 | os.path.join(os.path.dirname(os.path.realpath(__file__)), 'data'), |
||
64 | username, |
||
65 | '' |
||
66 | ) |
||
67 | if not os.path.isdir(self.IGDataPath): |
||
68 | os.mkdir(self.IGDataPath, 0777) |
||
69 | |||
70 | self.checkSettings(username) |
||
71 | |||
72 | self.http = HttpInterface(self) |
||
73 | |||
74 | self.setUser(username, password) |
||
75 | |||
76 | def setUser(self, username, password): |
||
77 | """ |
||
78 | Set the user. Manage multiple accounts. |
||
79 | |||
80 | :type username: str |
||
81 | :param username: Your Instagram username. |
||
82 | :type password: str |
||
83 | :param password: Your Instagram password. |
||
84 | : |
||
85 | """ |
||
86 | self.username = username |
||
87 | self.password = password |
||
88 | |||
89 | self.checkSettings(username) |
||
90 | |||
91 | self.uuid = SignatureUtils.generateUUID(True) |
||
92 | |||
93 | if os.path.isfile(self.IGDataPath + self.username + '-cookies.dat') and \ |
||
94 | (self.settings.get('username_id') != None) and \ |
||
95 | (self.settings.get('token') != None): |
||
96 | self.isLoggedIn = True |
||
97 | self.username_id = self.settings.get('username_id') |
||
98 | self.rank_token = self.username_id + '_' + self.uuid |
||
99 | self.token = self.settings.get('token') |
||
100 | else: |
||
101 | self.isLoggedIn = False |
||
102 | |||
103 | def checkSettings(self, username): |
||
104 | if self.customPath: |
||
105 | self.IGDataPath = os.path.join( |
||
106 | os.path.join(os.path.dirname(os.path.realpath(__file__)), 'data'), |
||
107 | username, |
||
108 | '' |
||
109 | ) |
||
110 | |||
111 | if not os.path.isdir(self.IGDataPath): os.mkdir(self.IGDataPath, 0777) |
||
112 | |||
113 | self.settings = Settings( |
||
114 | os.path.join(self.IGDataPath, 'settings-' + username + '.dat') |
||
115 | ) |
||
116 | if self.settings.get('version') is None: |
||
117 | self.settings.set('version', Constants.VERSION) |
||
118 | |||
119 | if (self.settings.get('user_agent') is None) or ( |
||
120 | LooseVersion(self.settings.get('version')) < LooseVersion(Constants.VERSION)): |
||
121 | userAgent = UserAgent(self) |
||
122 | ua = userAgent.buildUserAgent() |
||
123 | self.settings.set('version', Constants.VERSION) |
||
124 | self.settings.set('user_agent', ua) |
||
125 | |||
126 | def setProxy(self, proxy, port=None, username=None, password=None): |
||
127 | View Code Duplication | """ |
|
|
|||
128 | Set the proxy. |
||
129 | |||
130 | :type proxy: str |
||
131 | :param proxy: Full proxy string. Ex: user:[email protected]:8080 |
||
132 | Use $proxy = "" to clear proxy |
||
133 | :type port: int |
||
134 | :param port: Port of proxy |
||
135 | :type username: str |
||
136 | :param username: Username for proxy |
||
137 | :type password: str |
||
138 | :param password: Password for proxy |
||
139 | |||
140 | :raises: InstagramException |
||
141 | """ |
||
142 | self.proxy = proxy |
||
143 | |||
144 | if proxy == '': |
||
145 | return |
||
146 | |||
147 | proxy = parse_url(proxy) |
||
148 | |||
149 | if port and isinstance(port, int): |
||
150 | proxy['port'] = int(port) |
||
151 | |||
152 | if username and password: |
||
153 | proxy['user'] = username |
||
154 | proxy['pass'] = password |
||
155 | |||
156 | if proxy['host'] and proxy['port'] and isinstance(proxy['port'], int): |
||
157 | self.proxyHost = proxy['host'] + ':' + proxy['port'] |
||
158 | else: |
||
159 | raise InstagramException('Proxy host error. Please check ip address and port of proxy.') |
||
160 | |||
161 | if proxy['user'] and proxy['pass']: |
||
162 | self.proxyAuth = proxy['user'] + ':' + proxy['pass'] |
||
163 | |||
164 | def login(self, force=False): |
||
165 | """ |
||
166 | Login to Instagram. |
||
167 | |||
168 | :type force: bool |
||
169 | :param force: Force login to Instagram, this will create a new session |
||
170 | :return: Login data |
||
171 | :rtype List: |
||
172 | """ |
||
173 | if (not self.isLoggedIn) or force: |
||
174 | fetch = self.http.request( |
||
175 | 'si/fetch_headers/?challenge_type=signup&guid=' + SignatureUtils.generateUUID(False), None, True) |
||
176 | header = fetch[0] |
||
177 | response = ChallengeResponse(fetch[1]) |
||
178 | |||
179 | if not header or not response.isOk(): |
||
180 | raise InstagramException("Couldn't get challenge, check your connection") |
||
181 | # return response #FIXME unreachable code |
||
182 | |||
183 | match = re.search(r'^Set-Cookie: csrftoken=([^;]+)', fetch[0], re.MULTILINE) |
||
184 | if match: |
||
185 | self.token = match.group(1) |
||
186 | else: |
||
187 | raise InstagramException('Missing csfrtoken') |
||
188 | |||
189 | data = OrderedDict([ |
||
190 | ('username', self.username), |
||
191 | ('guid', self.uuid), |
||
192 | ('device_id', self.device_id), |
||
193 | ('password', self.password), |
||
194 | ('login_attempt_count', 0) |
||
195 | ]) |
||
196 | |||
197 | login = self.http.request('accounts/login/', SignatureUtils.generateSignature(json.dumps(data)), True) |
||
198 | response = LoginResponse(login[1]) |
||
199 | |||
200 | if not response.isOk(): raise InstagramException(response.getMessage()) |
||
201 | |||
202 | self.isLoggedIn = True |
||
203 | self.username_id = response.getUsernameId() |
||
204 | self.settings.set('username_id', self.username_id) |
||
205 | self.rank_token = self.username_id + '_' + self.uuid |
||
206 | match = re.search(r'^Set-Cookie: csrftoken=([^;]+)', login[0], re.MULTILINE) |
||
207 | if match: self.token = match.group(1) |
||
208 | self.settings.set('token', self.token) |
||
209 | |||
210 | self.syncFeatures() |
||
211 | self.timelineFeed() |
||
212 | self.getReelsTrayFeed() |
||
213 | self.autoCompleteUserList() |
||
214 | self.getv2Inbox() |
||
215 | self.getRecentActivity() |
||
216 | self.explore() |
||
217 | |||
218 | return response |
||
219 | |||
220 | check = self.timelineFeed() |
||
221 | |||
222 | if check.getMessage() == 'login_required': |
||
223 | self.login(True) |
||
224 | |||
225 | # self.getReelsTrayFeed() |
||
226 | # self.autoCompleteUserList() |
||
227 | self.getv2Inbox() |
||
228 | self.getRecentActivity() |
||
229 | # self.explore() |
||
230 | |||
231 | def syncFeatures(self): |
||
232 | data = json.dumps( |
||
233 | OrderedDict([ |
||
234 | ('_uuid', self.uuid), |
||
235 | ('_uid', self.username_id), |
||
236 | ('id', self.username_id), |
||
237 | ('_csrftoken', self.token), |
||
238 | ('experiments', Constants.EXPERIMENTS) |
||
239 | ]) |
||
240 | ) |
||
241 | return self.http.request('qe/sync/', SignatureUtils.generateSignature(data))[1] |
||
242 | |||
243 | def autoCompleteUserList(self): |
||
244 | return autoCompleteUserListResponse(self.http.request('friendships/autocomplete_user_list/')[1]) |
||
245 | |||
246 | def timelineFeed(self): |
||
247 | return TimelineFeedResponse(self.http.request('feed/timeline/')[1]) |
||
248 | |||
249 | def megaphoneLog(self): |
||
250 | return self.http.request('megaphone/log/')[1] |
||
251 | |||
252 | def getPendingInbox(self): |
||
253 | """ |
||
254 | Pending Inbox |
||
255 | |||
256 | :rtype: object |
||
257 | :return: Pending Inbox Data |
||
258 | """ |
||
259 | pendingInbox = PendingInboxResponse(self.http.request('direct_v2/pending_inbox/?')[1]) |
||
260 | |||
261 | if not pendingInbox.isOk(): |
||
262 | raise InstagramException(pendingInbox.getMessage() + "\n") |
||
263 | # return FIXME unreachable code |
||
264 | |||
265 | return pendingInbox |
||
266 | |||
267 | def explore(self): |
||
268 | """ |
||
269 | Explore Tab |
||
270 | |||
271 | :rtype: object |
||
272 | :return: Explore data |
||
273 | """ |
||
274 | explore = ExploreResponse(self.http.request('discover/explore/?')[1]) |
||
275 | |||
276 | if not explore.isOk(): |
||
277 | raise InstagramException(explore.getMessage() + "\n") |
||
278 | |||
279 | # return todo unreachable code |
||
280 | return explore |
||
281 | |||
282 | def expose(self): |
||
283 | data = json.dumps( |
||
284 | OrderedDict([ |
||
285 | ('_uuid', self.uuid), |
||
286 | ('_uid', self.username_id), |
||
287 | ('id', self.username_id), |
||
288 | ('_csrftoken', self.token), |
||
289 | ('experiment', 'ig_android_profile_contextual_feed') |
||
290 | ]) |
||
291 | ) |
||
292 | return ExposeResponse(self.http.request('qe/expose/', SignatureUtils.generateSignature(data))[1]) |
||
293 | |||
294 | def logout(self): |
||
295 | """ |
||
296 | Logout of Instagram. |
||
297 | |||
298 | :rtype: bool |
||
299 | :return: Returns true if logged out correctly |
||
300 | """ |
||
301 | logout = LogoutResponse(self.http.request('accounts/logout/')[1]) |
||
302 | |||
303 | if logout.isOk(): |
||
304 | return True |
||
305 | else: |
||
306 | return False |
||
307 | |||
308 | def uploadPhoto(self, photo, caption=None, upload_id=None, customPreview=None): |
||
309 | """ |
||
310 | Upload photo to Instagram. |
||
311 | |||
312 | :type photo: str |
||
313 | :param photo: Path to your photo |
||
314 | :type caption: str |
||
315 | :param caption: Caption to be included in your photo. |
||
316 | :rtype: object |
||
317 | :return: Upload data |
||
318 | """ |
||
319 | return self.http.uploadPhoto(photo, caption, upload_id, customPreview) |
||
320 | |||
321 | def uploadPhotoReel(self, photo, caption=None, upload_id=None, customPreview=None): |
||
322 | |||
323 | return self.http.uploadPhoto(photo, caption, upload_id, customPreview, True) |
||
324 | |||
325 | def uploadVideo(self, video, caption=None, customPreview=None): |
||
326 | """ |
||
327 | Upload video to Instagram. |
||
328 | |||
329 | :type video: str |
||
330 | :param photo: Path to your video |
||
331 | :type caption: str |
||
332 | :param caption: Caption to be included in your video. |
||
333 | :rtype: object |
||
334 | :return: Upload data |
||
335 | """ |
||
336 | return self.http.uploadVideo(video, caption), customPreview |
||
337 | |||
338 | def direct_share(self, media_id, recipients, text=None): |
||
339 | self.http.direct_share(media_id, recipients, text) |
||
340 | |||
341 | def direct_message(self, recipients, text): |
||
342 | """ |
||
343 | Send direct message to user by inbox |
||
344 | |||
345 | :type recipients: list|int |
||
346 | :param recipients: Users id |
||
347 | :type text: str |
||
348 | :param text: Text message |
||
349 | |||
350 | :return: void |
||
351 | """ |
||
352 | self.http.direct_message(recipients, text) |
||
353 | |||
354 | def directThread(self, threadId): |
||
355 | """ |
||
356 | Direct Thread Data |
||
357 | |||
358 | :type threadId: str |
||
359 | :param threadId: Thread Id |
||
360 | :rtype: object |
||
361 | :return: Direct Thread Data |
||
362 | """ |
||
363 | directThread = self.request("direct_v2/threads/" + str(threadId) + "/?")[1] |
||
364 | |||
365 | if directThread['status'] != 'ok': |
||
366 | raise InstagramException(directThread['message'] + "\n") |
||
367 | # return Fixme unreachable code |
||
368 | |||
369 | return directThread |
||
370 | |||
371 | def directThreadAction(self, threadId, threadAction): |
||
372 | """ |
||
373 | Direct Thread Action |
||
374 | |||
375 | :type threadId: str |
||
376 | :param threadId: Thread Id |
||
377 | :type threadAction: str |
||
378 | :param threadAction: Thread Action 'approve' OR 'decline' OR 'block' |
||
379 | :rtype: object |
||
380 | :return: Direct Thread Action Data |
||
381 | """ |
||
382 | data = json.dumps( |
||
383 | OrderedDict([ |
||
384 | ('_uuid', self.uuid), |
||
385 | ('_uid', self.username_id), |
||
386 | ('_csrftoken', self.token) |
||
387 | ]) |
||
388 | ) |
||
389 | return self.request("direct_v2/threads/" + str(threadId) + "/" + str(threadAction) + "/", |
||
390 | self.generateSignature(data))[1] |
||
391 | |||
392 | def configureVideo(self, upload_id, video, caption='', customPreview=None): |
||
393 | |||
394 | self.uploadPhoto(video, caption, upload_id, customPreview) |
||
395 | size = Image.open(video).size[0] |
||
396 | |||
397 | post = json.dumps( |
||
398 | OrderedDict([ |
||
399 | ('upload_id', upload_id), |
||
400 | ('source_type', 3), |
||
401 | ('poster_frame_index', 0), |
||
402 | ('length', 0.00), |
||
403 | ('audio_muted', False), |
||
404 | ('filter_type', '0'), |
||
405 | ('video_result', 'deprecated'), |
||
406 | ('clips', OrderedDict([ |
||
407 | ('length', Utils.getSeconds(video)), |
||
408 | ('source_type', '3'), |
||
409 | ('camera_position', 'back') |
||
410 | ])), |
||
411 | ('extra', OrderedDict([ |
||
412 | ('source_width', 960), |
||
413 | ('source_height', 1280) |
||
414 | ])), |
||
415 | |||
416 | ('device', OrderedDict([ |
||
417 | ('manufacturer', self.settings.get('manufacturer')), |
||
418 | ('model', self.settings.get('model')), |
||
419 | ('android_version', Constants.ANDROID_VERSION), |
||
420 | ('android_release', Constants.ANDROID_RELEASE) |
||
421 | ])), |
||
422 | ('_csrftoken', self.token), |
||
423 | ('_uuid', self.uuid), |
||
424 | ('_uid', self.username_id), |
||
425 | ('caption', caption) |
||
426 | |||
427 | ]) |
||
428 | |||
429 | ) |
||
430 | |||
431 | post = post.replace('"length":0', '"length":0.00') |
||
432 | |||
433 | return ConfigureVideoResponse( |
||
434 | self.http.request('media/configure/?video=1', SignatureUtils.generateSignature(post))[1]) |
||
435 | |||
436 | def configure(self, upload_id, photo, caption=''): |
||
437 | |||
438 | size = Image.open(photo).size[0] |
||
439 | |||
440 | post = json.dumps( |
||
441 | OrderedDict([ |
||
442 | ('upload_id', upload_id), |
||
443 | ('camera_model', self.settings.get('model').replace(" ", "")), |
||
444 | ('source_type', 3), |
||
445 | ('date_time_original', time.strftime('%Y:%m:%d %H:%M:%S')), |
||
446 | ('camera_make', self.settings.get('manufacturer')), |
||
447 | ('edits', OrderedDict([ |
||
448 | ('crop_original_size', [size, size]), |
||
449 | ('crop_zoom', 1.3333334), |
||
450 | ('crop_center', [0.0, -0.0]) |
||
451 | ])), |
||
452 | ('extra', OrderedDict([ |
||
453 | ('source_width', size), |
||
454 | ('source_height', size) |
||
455 | ])), |
||
456 | |||
457 | ('device', OrderedDict([ |
||
458 | ('manufacturer', self.settings.get('manufacturer')), |
||
459 | ('model', self.settings.get('model')), |
||
460 | ('android_version', Constants.ANDROID_VERSION), |
||
461 | ('android_release', Constants.ANDROID_RELEASE) |
||
462 | ])), |
||
463 | ('_csrftoken', self.token), |
||
464 | ('_uuid', self.uuid), |
||
465 | ('_uid', self.username_id), |
||
466 | ('caption', caption) |
||
467 | |||
468 | ]) |
||
469 | ) |
||
470 | post = post.replace('"crop_center":[0,0]', '"crop_center":[0.0,-0.0]') |
||
471 | |||
472 | return ConfigureResponse(self.http.request('media/configure/', SignatureUtils.generateSignature(post))[1]) |
||
473 | |||
474 | def configureToReel(self, upload_id, photo): |
||
475 | |||
476 | size = Image.open(photo).size[0] |
||
477 | |||
478 | post = json.dumps( |
||
479 | OrderedDict([ |
||
480 | ('upload_id', upload_id), |
||
481 | ('source_type', 3), |
||
482 | ('edits', OrderedDict([ |
||
483 | ('crop_original_size', [size, size]), |
||
484 | ('crop_zoom', 1.3333334), |
||
485 | ('crop_center', [0.0, 0.0]) |
||
486 | ])), |
||
487 | ('extra', OrderedDict([ |
||
488 | ('source_width', size), |
||
489 | ('source_height', size) |
||
490 | ])), |
||
491 | |||
492 | ('device', OrderedDict([ |
||
493 | ('manufacturer', self.settings.get('manufacturer')), |
||
494 | ('model', self.settings.get('model')), |
||
495 | ('android_version', Constants.ANDROID_VERSION), |
||
496 | ('android_release', Constants.ANDROID_RELEASE) |
||
497 | ])), |
||
498 | ('_csrftoken', self.token), |
||
499 | ('_uuid', self.uuid), |
||
500 | ('_uid', self.username_id) |
||
501 | |||
502 | ]) |
||
503 | ) |
||
504 | post = post.replace('"crop_center":[0,0]', '"crop_center":[0.0,0.0]') |
||
505 | |||
506 | return ConfigureResponse( |
||
507 | self.http.request('media/configure_to_reel/', SignatureUtils.generateSignature(post))[1]) |
||
508 | |||
509 | def editMedia(self, mediaId, captionText=''): |
||
510 | """ |
||
511 | Edit media. |
||
512 | :type mediaId: str |
||
513 | :param mediaId: Media id |
||
514 | :type captionText: str |
||
515 | :param captionText: Caption text |
||
516 | :rtype: object |
||
517 | :return: edit media data |
||
518 | """ |
||
519 | data = json.dumps( |
||
520 | OrderedDict([ |
||
521 | ('_uuid', self.uuid), |
||
522 | ('_uid', self.username_id), |
||
523 | ('_csrftoken', self.token), |
||
524 | ('caption_text', captionText) |
||
525 | ]) |
||
526 | ) |
||
527 | return self.http.request("media/" + mediaId + "/edit_media/", SignatureUtils.generateSignature(data))[1] |
||
528 | |||
529 | def removeSelftag(self, mediaId): |
||
530 | """ |
||
531 | Remove yourself from a tagged media. |
||
532 | :type mediaId: str |
||
533 | :param mediaId: Media id |
||
534 | :rtype: object |
||
535 | :return: edit media data |
||
536 | """ |
||
537 | data = json.dumps( |
||
538 | OrderedDict([ |
||
539 | ('_uuid', self.uuid), |
||
540 | ('_uid', self.username_id), |
||
541 | ('_csrftoken', self.token) |
||
542 | ]) |
||
543 | ) |
||
544 | return self.http.request("usertags/" + mediaId + "/remove/", SignatureUtils.generateSignature(data))[1] |
||
545 | |||
546 | def mediaInfo(self, mediaId): |
||
547 | """ |
||
548 | Media info |
||
549 | :type mediaId: str |
||
550 | :param mediaId: Media id |
||
551 | :rtype: object |
||
552 | :return: delete request data |
||
553 | """ |
||
554 | data = json.dumps( |
||
555 | OrderedDict([ |
||
556 | ('_uuid', self.uuid), |
||
557 | ('_uid', self.username_id), |
||
558 | ('_csrftoken', self.token), |
||
559 | ('media_id', mediaId) |
||
560 | ]) |
||
561 | ) |
||
562 | return MediaInfoResponse( |
||
563 | self.http.request("media/" + mediaId + "/info/", SignatureUtils.generateSignature(data))[1]) |
||
564 | |||
565 | def deleteMedia(self, mediaId): |
||
566 | """ |
||
567 | Delete photo or video. |
||
568 | :type mediaId: str |
||
569 | :param mediaId: Media id |
||
570 | :rtype: object |
||
571 | :return: delete request data |
||
572 | """ |
||
573 | data = json.dumps( |
||
574 | OrderedDict([ |
||
575 | ('_uuid', self.uuid), |
||
576 | ('_uid', self.username_id), |
||
577 | ('_csrftoken', self.token), |
||
578 | ('media_id', mediaId) |
||
579 | ]) |
||
580 | ) |
||
581 | return self.http.request("media/" + mediaId + "/delete/", SignatureUtils.generateSignature(data))[1] |
||
582 | |||
583 | def comment(self, mediaId, commentText): |
||
584 | """ |
||
585 | Comment media. |
||
586 | :type mediaId: str |
||
587 | :param mediaId: Media id |
||
588 | :type commentText: str |
||
589 | :param commentText: Comment Text |
||
590 | :rtype: object |
||
591 | :return: comment media data |
||
592 | """ |
||
593 | data = json.dumps( |
||
594 | OrderedDict([ |
||
595 | ('_uuid', self.uuid), |
||
596 | ('_uid', self.username_id), |
||
597 | ('_csrftoken', self.token), |
||
598 | ('comment_text', commentText) |
||
599 | ]) |
||
600 | ) |
||
601 | return self.http.request("media/" + mediaId + "/comment/", SignatureUtils.generateSignature(data))[1] |
||
602 | |||
603 | def deleteComment(self, mediaId, commentId): |
||
604 | """ |
||
605 | Delete Comment. |
||
606 | :type mediaId: str |
||
607 | :param mediaId: Media ID |
||
608 | :type commentId: str |
||
609 | :param commentId: Comment ID |
||
610 | :rtype: object |
||
611 | :return: Delete comment data |
||
612 | """ |
||
613 | data = json.dumps( |
||
614 | OrderedDict([ |
||
615 | ('_uuid', self.uuid), |
||
616 | ('_uid', self.username_id), |
||
617 | ('_csrftoken', self.token) |
||
618 | ]) |
||
619 | ) |
||
620 | return \ |
||
621 | self.http.request("media/" + mediaId + "/comment/" + commentId + "/delete/", |
||
622 | SignatureUtils.generateSignature(data))[1] |
||
623 | |||
624 | def deleteCommentsBulk(self, mediaId, commentIds): |
||
625 | """ |
||
626 | Delete Comment Bulk. |
||
627 | |||
628 | :type mediaId: str |
||
629 | :param mediaId: Media ID |
||
630 | :type commentIds: list |
||
631 | :param commentIds: List of comments to delete |
||
632 | :rtype: object |
||
633 | :return: Delete Comment Bulk Data |
||
634 | """ |
||
635 | if not isinstance(commentIds, list): |
||
636 | commentIds = [commentIds] |
||
637 | |||
638 | string = [] |
||
639 | for commentId in commentIds: |
||
640 | string.append(str(commentId)) |
||
641 | |||
642 | comment_ids_to_delete = ','.join(string) |
||
643 | |||
644 | data = json.dumps( |
||
645 | OrderedDict([ |
||
646 | ('_uuid', self.uuid), |
||
647 | ('_uid', self.username_id), |
||
648 | ('_csrftoken', self.token), |
||
649 | ('comment_ids_to_delete', comment_ids_to_delete) |
||
650 | ]) |
||
651 | ) |
||
652 | return self.http.request("media/" + mediaId + "/comment/bulk_delete/", |
||
653 | SignatureUtils.generateSignature(data))[1] |
||
654 | |||
655 | def changeProfilePicture(self, photo): |
||
656 | """ |
||
657 | Sets account to public. |
||
658 | :type photo: str |
||
659 | :param photo: Path to photo |
||
660 | """ |
||
661 | self.http.changeProfilePicture(photo) |
||
662 | |||
663 | def removeProfilePicture(self): |
||
664 | """ |
||
665 | Remove profile picture. |
||
666 | :rtype: object |
||
667 | :return: status request data |
||
668 | """ |
||
669 | data = json.dumps( |
||
670 | OrderedDict([('_uuid', self.uuid), ('_uid', self.username_id), ('_csrftoken', self.token)]) |
||
671 | ) |
||
672 | return self.http.request('accounts/remove_profile_picture/', SignatureUtils.generateSignature(data))[1] |
||
673 | |||
674 | def setPrivateAccount(self): |
||
675 | """ |
||
676 | Sets account to private. |
||
677 | |||
678 | :rtype: object |
||
679 | :return: status request data |
||
680 | """ |
||
681 | data = json.dumps( |
||
682 | OrderedDict([ |
||
683 | ('_uuid', self.uuid), |
||
684 | ('_uid', self.username_id), |
||
685 | ('_csrftoken', self.token) |
||
686 | ]) |
||
687 | ) |
||
688 | return self.http.request('accounts/set_private/', SignatureUtils.generateSignature(data))[1] |
||
689 | |||
690 | def setPublicAccount(self): |
||
691 | """ |
||
692 | Sets account to public. |
||
693 | :rtype: object |
||
694 | :return: status request data |
||
695 | """ |
||
696 | data = json.dumps( |
||
697 | OrderedDict([ |
||
698 | ('_uuid', self.uuid), |
||
699 | ('_uid', self.username_id), |
||
700 | ('_csrftoken', self.token) |
||
701 | ]) |
||
702 | ) |
||
703 | return self.http.request('accounts/set_public/', SignatureUtils.generateSignature(data))[1] |
||
704 | |||
705 | def getProfileData(self): |
||
706 | """ |
||
707 | Get personal profile data. |
||
708 | :rtype: object |
||
709 | :return: |
||
710 | """ |
||
711 | data = json.dumps( |
||
712 | OrderedDict([ |
||
713 | ('_uuid', self.uuid), |
||
714 | ('_uid', self.username_id), |
||
715 | ('_csrftoken', self.token) |
||
716 | ]) |
||
717 | ) |
||
718 | return ProfileResponse( |
||
719 | self.http.request('accounts/current_user/?edit=true', SignatureUtils.generateSignature(data))[1]) |
||
720 | |||
721 | def editProfile(self, url, phone, first_name, biography, email, gender): |
||
722 | """ |
||
723 | Edit profile. |
||
724 | :type url: str |
||
725 | :param url: Url - website. "" for nothing |
||
726 | :type phone: str |
||
727 | :param phone: Phone number. "" for nothing |
||
728 | :type first_name: str |
||
729 | :param first_name: Name. "" for nothing |
||
730 | :type email: str |
||
731 | :param email: Email. Required. |
||
732 | :type gender: int |
||
733 | :param gender: Gender. male = 1 , female = 0 |
||
734 | :rtype: object |
||
735 | :return: edit profile data |
||
736 | """ |
||
737 | data = json.dumps( |
||
738 | OrderedDict([ |
||
739 | ('_uuid', self.uuid), |
||
740 | ('_uid', self.username_id), |
||
741 | ('_csrftoken', self.token), |
||
742 | ('external_url', url), |
||
743 | ('phone_number', phone), |
||
744 | ('username', self.username), |
||
745 | ('first_name', first_name), |
||
746 | ('biography', biography), |
||
747 | ('email', email), |
||
748 | ('gender', gender) |
||
749 | ]) |
||
750 | ) |
||
751 | |||
752 | return ProfileResponse(self.http.request('accounts/edit_profile/', SignatureUtils.generateSignature(data))[1]) |
||
753 | |||
754 | def changePassword(self, oldPassword, newPassword): |
||
755 | """ |
||
756 | Change Password. |
||
757 | |||
758 | :type oldPassword: str |
||
759 | :param oldPassword: Old Password |
||
760 | :type newPassword: str |
||
761 | :param newPassword: New Password |
||
762 | :rtype: object |
||
763 | :return: Change Password Data |
||
764 | """ |
||
765 | |||
766 | data = json.dumps( |
||
767 | OrderedDict([ |
||
768 | ('_uuid', self.uuid), |
||
769 | ('_uid', self.username_id), |
||
770 | ('_csrftoken', self.token), |
||
771 | ('old_password', oldPassword), |
||
772 | ('new_password1', newPassword), |
||
773 | ('new_password2', newPassword) |
||
774 | ]) |
||
775 | ) |
||
776 | return self.http.request('accounts/change_password/', SignatureUtils.generateSignature(data))[1] |
||
777 | |||
778 | def getUsernameInfo(self, usernameId): |
||
779 | """ |
||
780 | Get username info. |
||
781 | :param usernameId: Username id |
||
782 | :rtype: object |
||
783 | :return: Username data |
||
784 | """ |
||
785 | return self.http.request("users/" + str(usernameId) + "/info/")[1] |
||
786 | |||
787 | def getSelfUsernameInfo(self): |
||
788 | """ |
||
789 | Get self username info. |
||
790 | :rtype: object |
||
791 | :return: Username data |
||
792 | """ |
||
793 | return self.getUsernameInfo(self.username_id) |
||
794 | |||
795 | def getRecentActivity(self): |
||
796 | """ |
||
797 | Get recent activity. |
||
798 | :rtype: object |
||
799 | :return: Recent activity data |
||
800 | """ |
||
801 | activity = self.http.request('news/inbox/')[1] |
||
802 | |||
803 | if activity['status'] != 'ok': |
||
804 | raise InstagramException(activity['message'] + "\n") |
||
805 | |||
806 | return activity |
||
807 | |||
808 | def getFollowingRecentActivity(self): |
||
809 | """ |
||
810 | Get recent activity from accounts followed. |
||
811 | |||
812 | :rtype: object |
||
813 | :return: Recent activity data of follows |
||
814 | """ |
||
815 | activity = self.http.request('news/?')[1] |
||
816 | if activity['status'] != 'ok': |
||
817 | raise InstagramException(activity['message'] + "\n") |
||
818 | |||
819 | return activity |
||
820 | |||
821 | def getv2Inbox(self): |
||
822 | """ |
||
823 | I dont know this yet. |
||
824 | :rtype: object |
||
825 | :return: v2 inbox data |
||
826 | """ |
||
827 | inbox = V2InboxResponse(self.http.request('direct_v2/inbox/?')[1]) |
||
828 | |||
829 | if not inbox.isOk(): |
||
830 | raise InstagramException(inbox.getMessage() + "\n") |
||
831 | |||
832 | return inbox |
||
833 | |||
834 | def getUserTags(self, usernameId): |
||
835 | """ |
||
836 | Get user tags. |
||
837 | :type usernameId: str |
||
838 | :param usernameId: |
||
839 | :rtype: object |
||
840 | :return: user tags data |
||
841 | """ |
||
842 | tags = UsertagsResponse(self.http.request("usertags/" + str(usernameId) + "/feed/?rank_token=" + self.rank_token |
||
843 | + "&ranked_content=true&")[1]) |
||
844 | if not tags.isOk(): |
||
845 | raise InstagramException(tags.getMessage() + "\n") |
||
846 | |||
847 | return tags |
||
848 | |||
849 | def getSelfUserTags(self): |
||
850 | """ |
||
851 | Get self user tags. |
||
852 | :rtype: object |
||
853 | :return: self user tags data |
||
854 | """ |
||
855 | return self.getUserTags(self.username_id) |
||
856 | |||
857 | def tagFeed(self, tag): |
||
858 | """ |
||
859 | Get tagged media. |
||
860 | :type tag: str |
||
861 | :param tag: |
||
862 | :rtype: object |
||
863 | :return: |
||
864 | """ |
||
865 | userFeed = TagFeedResponse( |
||
866 | self.http.request("feed/tag/" + tag + "/?rank_token=" + self.rank_token + "&ranked_content=true&")[1]) |
||
867 | |||
868 | if not userFeed.isOk(): |
||
869 | raise InstagramException(userFeed.getMessage() + "\n") |
||
870 | |||
871 | return userFeed |
||
872 | |||
873 | def getMediaLikers(self, mediaId): |
||
874 | """ |
||
875 | Get media likers. |
||
876 | :type mediaId: str |
||
877 | :param mediaId: |
||
878 | :rtype: object |
||
879 | :return: |
||
880 | """ |
||
881 | likers = MediaLikersResponse(self.http.request("media/" + mediaId + "/likers/")[1]) |
||
882 | if not likers.isOk(): |
||
883 | raise InstagramException(likers.getMessage() + "\n") |
||
884 | # return #fixme unreachable code |
||
885 | |||
886 | return likers |
||
887 | |||
888 | def getGeoMedia(self, usernameId): |
||
889 | """ |
||
890 | Get user locations media. |
||
891 | :type usernameId: str |
||
892 | :param usernameId: Username id |
||
893 | :rtype: object |
||
894 | :return: Geo Media data |
||
895 | """ |
||
896 | locations = self.http.request("maps/user/" + str(usernameId) + "/")[1] |
||
897 | |||
898 | if locations['status'] != 'ok': |
||
899 | raise InstagramException(locations['message'] + "\n") |
||
900 | |||
901 | return locations |
||
902 | |||
903 | def getSelfGeoMedia(self): |
||
904 | """ |
||
905 | Get self user locations media. |
||
906 | :rtype: object |
||
907 | :return: Geo Media data |
||
908 | """ |
||
909 | return self.getGeoMedia(self.username_id) |
||
910 | |||
911 | def searchLocation(self, latitude, longitude): |
||
912 | locations = LocationResponse(self.http.request( |
||
913 | "location_search/?rank_token=" + self.rank_token + "&latitude=" + latitude + "&longitude=" + longitude)[1]) |
||
914 | |||
915 | if not locations.isOk(): |
||
916 | raise InstagramException(locations.getMessage() + "\n") |
||
917 | # return fixme unreachable code |
||
918 | |||
919 | return locations |
||
920 | |||
921 | def fbUserSearch(self, query): |
||
922 | """ |
||
923 | facebook user search. |
||
924 | :type query: str |
||
925 | :param query: |
||
926 | :rtype: object |
||
927 | :return: query data |
||
928 | """ |
||
929 | query = urllib.quote(query) |
||
930 | query = \ |
||
931 | self.http.request("fbsearch/topsearch/?context=blended&query=" + query + "&rank_token=" + self.rank_token)[ |
||
932 | 1] |
||
933 | |||
934 | if query['status'] != 'ok': |
||
935 | raise InstagramException(query['message'] + "\n") |
||
936 | |||
937 | return query |
||
938 | |||
939 | def searchUsers(self, query): |
||
940 | """ |
||
941 | Search users. |
||
942 | :type query: str |
||
943 | :param query: |
||
944 | :rtype: object |
||
945 | :return: query data |
||
946 | """ |
||
947 | query = self.http.request( |
||
948 | 'users/search/?ig_sig_key_version=' + Constants.SIG_KEY_VERSION \ |
||
949 | + "&is_typeahead=true&query=" + query + "&rank_token=" + self.rank_token)[1] |
||
950 | |||
951 | if query['status'] != 'ok': |
||
952 | raise InstagramException(query['message'] + "\n") |
||
953 | |||
954 | return query |
||
955 | |||
956 | def searchUsername(self, usernameName): |
||
957 | """ |
||
958 | Search exact username |
||
959 | |||
960 | :type usernameName: str |
||
961 | :param usernameName: username as STRING not an id |
||
962 | |||
963 | :rtype: object |
||
964 | :return: query data |
||
965 | """ |
||
966 | query = UsernameInfoResponse(self.http.request("users/" + usernameName + "/usernameinfo/")[1]) |
||
967 | |||
968 | if not query.isOk(): |
||
969 | raise InstagramException(query.getMessage() + "\n") |
||
970 | |||
971 | return query |
||
972 | |||
973 | def getUsernameId(self, username): |
||
974 | return self.searchUsername(username).getUsernameId() |
||
975 | |||
976 | def syncFromAdressBook(self, contacts): |
||
977 | """ |
||
978 | Search users using addres book. |
||
979 | :type contacts: list |
||
980 | :param contacts: |
||
981 | :rtype: object |
||
982 | :return: |
||
983 | """ |
||
984 | data = OrderedDict([( |
||
985 | ('contacts=', json.dumps(contacts)) |
||
986 | )]) |
||
987 | return self.http.request('address_book/link/?include=extra_display_name,thumbnails', data)[1] |
||
988 | |||
989 | def searchTags(self, query): |
||
990 | """ |
||
991 | Search tags. |
||
992 | :type query: str |
||
993 | :param query: |
||
994 | :rtype: object |
||
995 | :return: query data |
||
996 | """ |
||
997 | query = self.http.request("tags/search/?is_typeahead=true&q=" + query + "&rank_token=" + self.rank_token)[1] |
||
998 | |||
999 | if query['status'] != 'ok': |
||
1000 | raise InstagramException(query['message'] + "\n") |
||
1001 | |||
1002 | return query |
||
1003 | |||
1004 | def getTimeline(self, maxid=None): |
||
1005 | """ |
||
1006 | Get timeline data. |
||
1007 | :rtype: object |
||
1008 | :return: timeline data |
||
1009 | """ |
||
1010 | timeline = self.http.request( |
||
1011 | "feed/timeline/?rank_token=" + self.rank_token + "&ranked_content=true" + |
||
1012 | (("&max_id=" + str(maxid)) if maxid is not None else '') |
||
1013 | )[1] |
||
1014 | |||
1015 | if timeline['status'] != 'ok': |
||
1016 | raise InstagramException(timeline['message'] + "\n") |
||
1017 | |||
1018 | return timeline |
||
1019 | |||
1020 | def getReelsTrayFeed(self): |
||
1021 | feed = ReelsTrayFeedResponse(self.http.request('feed/reels_tray/')[1]) |
||
1022 | if not feed.isOk(): |
||
1023 | raise InstagramException(feed.getMessage() + "\n") |
||
1024 | # return todo Unreachable code |
||
1025 | |||
1026 | return feed |
||
1027 | |||
1028 | def getUserFeed(self, usernameId, maxid=None, minTimestamp=None): |
||
1029 | """ |
||
1030 | Get user feed. |
||
1031 | :type usernameId: str |
||
1032 | :param usernameId: Username id |
||
1033 | :type maxid: str |
||
1034 | :param maxid: Max Id |
||
1035 | :type minTimestamp: str |
||
1036 | :param minTimestamp: Min timestamp |
||
1037 | :rtype: object |
||
1038 | :return: User feed data |
||
1039 | :raises: InstagramException |
||
1040 | """ |
||
1041 | userFeed = UserFeedResponse(self.http.request("feed/user/" + str(usernameId) + "/?rank_token=" + self.rank_token |
||
1042 | + (("&max_id=" + str(maxid)) if maxid is not None else '') \ |
||
1043 | + (("&minTimestamp=" + str(minTimestamp)) if minTimestamp is not None else '') \ |
||
1044 | + "&ranked_content=true" |
||
1045 | )[1]) |
||
1046 | |||
1047 | if not userFeed.isOk(): |
||
1048 | raise InstagramException(userFeed.getMessage() + "\n") |
||
1049 | |||
1050 | return userFeed |
||
1051 | |||
1052 | def getHashtagFeed(self, hashtagString, maxid=''): |
||
1053 | """ |
||
1054 | Get hashtag feed. |
||
1055 | :type hashtagString: str |
||
1056 | :param hashtagString: Hashtag string, not including the # |
||
1057 | :rtype: object |
||
1058 | :return: Hashtag feed data |
||
1059 | """ |
||
1060 | if maxid == '': |
||
1061 | endpoint = "feed/tag/" + hashtagString + "/?rank_token=" + self.rank_token + "&ranked_content=true&" |
||
1062 | else: |
||
1063 | endpoint = "feed/tag/" + hashtagString + "/?max_id=" \ |
||
1064 | + maxid + "&rank_token=" + self.rank_token + "&ranked_content=true&" |
||
1065 | hashtagFeed = self.http.request(endpoint)[1] |
||
1066 | if hashtagFeed['status'] != 'ok': |
||
1067 | raise InstagramException(hashtagFeed['message'] + "\n") |
||
1068 | |||
1069 | return hashtagFeed |
||
1070 | |||
1071 | def searchFBLocation(self, query): |
||
1072 | """ |
||
1073 | Get locations. |
||
1074 | :type query: str |
||
1075 | :param query: search query |
||
1076 | :rtype: object |
||
1077 | :return: Location location data |
||
1078 | """ |
||
1079 | query = urllib.quote(query) |
||
1080 | endpoint = "fbsearch/places/?rank_token=" + self.rank_token + "&query=" + query |
||
1081 | |||
1082 | locationFeed = self.http.request(endpoint)[1] |
||
1083 | |||
1084 | if locationFeed['status'] != 'ok': |
||
1085 | raise InstagramException(locationFeed['message'] + "\n") |
||
1086 | |||
1087 | return locationFeed |
||
1088 | |||
1089 | def getLocationFeed(self, locationId, maxid=''): |
||
1090 | """ |
||
1091 | Get location feed. |
||
1092 | :type locationId: str |
||
1093 | :param locationId: location id |
||
1094 | :rtype: object |
||
1095 | :return: Location feed data |
||
1096 | """ |
||
1097 | if maxid is '': |
||
1098 | endpoint = "feed/location/" + locationId + "/?rank_token=" + self.rank_token + "&ranked_content=true&" |
||
1099 | else: |
||
1100 | endpoint = "feed/location/" + locationId + "/?max_id=" \ |
||
1101 | + maxid + "&rank_token=" + self.rank_token + "&ranked_content=true&" |
||
1102 | |||
1103 | locationFeed = self.http.request(endpoint)[1] |
||
1104 | |||
1105 | if locationFeed['status'] != 'ok': |
||
1106 | raise InstagramException(locationFeed['message'] + "\n") |
||
1107 | |||
1108 | return locationFeed |
||
1109 | |||
1110 | def getSelfUserFeed(self, max_id=None): |
||
1111 | """ |
||
1112 | Get self user feed. |
||
1113 | :rtype: object |
||
1114 | :return: User feed data |
||
1115 | """ |
||
1116 | return self.getUserFeed(self.username_id, max_id) |
||
1117 | |||
1118 | def getPopularFeed(self): |
||
1119 | """ |
||
1120 | Get popular feed. |
||
1121 | :rtype: object |
||
1122 | :return: popular feed data |
||
1123 | """ |
||
1124 | popularFeed = self.http.request("feed/popular/?people_teaser_supported=1&rank_token=" \ |
||
1125 | + self.rank_token + "&ranked_content=true&")[1] |
||
1126 | |||
1127 | if popularFeed['status'] != 'ok': |
||
1128 | raise InstagramException(popularFeed['message'] + "\n") |
||
1129 | |||
1130 | return popularFeed |
||
1131 | |||
1132 | def getUserFollowings(self, usernameId, maxid=''): |
||
1133 | """ |
||
1134 | Get user followings. |
||
1135 | :type usernameId: str |
||
1136 | :param usernameId: Username id |
||
1137 | |||
1138 | :rtype: object |
||
1139 | :return: followers data |
||
1140 | """ |
||
1141 | return FollowingResponse(self.http.request( |
||
1142 | "friendships/" + usernameId + "/following/?max_id=" + maxid + "&ig_sig_key_version=" \ |
||
1143 | + Constants.SIG_KEY_VERSION + "&rank_token=" + self.rank_token)[1]) |
||
1144 | |||
1145 | def getUserFollowers(self, usernameId, maxid=''): |
||
1146 | """ |
||
1147 | Get user followers. |
||
1148 | :type usernameId: str |
||
1149 | :param usernameId: Username id |
||
1150 | |||
1151 | :rtype: object |
||
1152 | :return: followers data |
||
1153 | """ |
||
1154 | return FollowerResponse(self.http.request( |
||
1155 | "friendships/" + usernameId + "/followers/?max_id=" + maxid \ |
||
1156 | + "&ig_sig_key_version=" + Constants.SIG_KEY_VERSION + "&rank_token=" + self.rank_token)[1]) |
||
1157 | |||
1158 | def getSelfUserFollowers(self): |
||
1159 | """ |
||
1160 | Get self user followers. |
||
1161 | |||
1162 | :rtype: object |
||
1163 | :return: followers data |
||
1164 | """ |
||
1165 | return self.getUserFollowers(self.username_id) |
||
1166 | |||
1167 | def getSelfUsersFollowing(self): |
||
1168 | """ |
||
1169 | Get self users we are following. |
||
1170 | |||
1171 | :rtype: object |
||
1172 | :return: users we are following data |
||
1173 | """ |
||
1174 | return self.getUserFollowings(self.username_id) |
||
1175 | |||
1176 | def like(self, mediaId): |
||
1177 | """ |
||
1178 | Like photo or video. |
||
1179 | |||
1180 | :type mediaId: str |
||
1181 | :param mediaId: Media id |
||
1182 | :rtype: object |
||
1183 | :return: status request |
||
1184 | """ |
||
1185 | data = json.dumps( |
||
1186 | OrderedDict([ |
||
1187 | ('_uuid', self.uuid), |
||
1188 | ('_uid', self.username_id), |
||
1189 | ('_csrftoken', self.token), |
||
1190 | ('media_id', mediaId) |
||
1191 | ]) |
||
1192 | ) |
||
1193 | return self.http.request("media/" + mediaId + "/like/", SignatureUtils.generateSignature(data))[1] |
||
1194 | |||
1195 | def unlike(self, mediaId): |
||
1196 | """ |
||
1197 | Unlike photo or video. |
||
1198 | |||
1199 | :type mediaId: str |
||
1200 | :param mediaId: Media id |
||
1201 | :rtype: object |
||
1202 | :return: status request |
||
1203 | """ |
||
1204 | data = json.dumps( |
||
1205 | OrderedDict([ |
||
1206 | ('_uuid', self.uuid), |
||
1207 | ('_uid', self.username_id), |
||
1208 | ('_csrftoken', self.token), |
||
1209 | ('media_id', mediaId) |
||
1210 | ]) |
||
1211 | ) |
||
1212 | return self.http.request("media/" + mediaId + "/unlike/", SignatureUtils.generateSignature(data))[1] |
||
1213 | |||
1214 | def getMediaComments(self, mediaId): |
||
1215 | """ |
||
1216 | Get media comments. |
||
1217 | :type mediaId: str |
||
1218 | :param mediaId: Media id |
||
1219 | :rtype: object |
||
1220 | :return: Media comments data |
||
1221 | """ |
||
1222 | return self.http.request("media/" + mediaId + "/comments/?")[1] |
||
1223 | |||
1224 | def setNameAndPhone(self, name='', phone=''): |
||
1225 | """ |
||
1226 | Set name and phone (Optional). |
||
1227 | :type name: str |
||
1228 | :param name: |
||
1229 | :type phone: str |
||
1230 | :param phone: |
||
1231 | :rtype: object |
||
1232 | :return: Set status data |
||
1233 | """ |
||
1234 | data = json.dumps( |
||
1235 | OrderedDict([ |
||
1236 | ('_uuid', self.uuid), |
||
1237 | ('_uid', self.username_id), |
||
1238 | ('first_name', name), |
||
1239 | ('phone_number', phone), |
||
1240 | ('_csrftoken', self.token) |
||
1241 | ]) |
||
1242 | ) |
||
1243 | |||
1244 | return self.http.request("accounts/set_phone_and_name/", SignatureUtils.generateSignature(data))[1] |
||
1245 | |||
1246 | def getDirectShare(self): |
||
1247 | """ |
||
1248 | Get direct share. |
||
1249 | |||
1250 | :rtype: object |
||
1251 | :return: Direct share data |
||
1252 | """ |
||
1253 | return self.http.request('direct_share/inbox/?')[1] |
||
1254 | |||
1255 | def backup(self): |
||
1256 | """ |
||
1257 | Backups all your uploaded photos :). |
||
1258 | """ |
||
1259 | go = False |
||
1260 | while True: |
||
1261 | if not go: |
||
1262 | myUploads = self.getSelfUserFeed() |
||
1263 | else: |
||
1264 | myUploads = self.getSelfUserFeed(myUploads.getNextMaxId() if myUploads.getNextMaxId() else None) |
||
1265 | |||
1266 | if not os.path.isdir(self.IGDataPath + 'backup/'): |
||
1267 | os.mkdir(self.IGDataPath + 'backup/') |
||
1268 | |||
1269 | for item in myUploads.getItems(): |
||
1270 | dir_name = self.IGDataPath + 'backup/' + self.username + "-" + time.strftime('%Y-%m-%d') |
||
1271 | if not os.path.isdir(dir_name): |
||
1272 | os.mkdir(dir_name) |
||
1273 | |||
1274 | if item.getVideoVersions(): |
||
1275 | file_put_contents( |
||
1276 | os.path.join(dir_name, item.getMediaId() + '.mp4'), |
||
1277 | urllib.urlopen(item.getVideoVersions()[0].getUrl()).read() |
||
1278 | ) # todo test and remove below |
||
1279 | else: |
||
1280 | file_put_contents( |
||
1281 | os.path.join(dir_name, item.getMediaId() + '.jpg'), |
||
1282 | urllib.urlopen(item.getImageVersions()[0].getUrl()).read() |
||
1283 | ) # todo test and remove below |
||
1284 | |||
1285 | # urllib.urlretrieve( |
||
1286 | # item['image_versions2']['candidates'][0]['url'], |
||
1287 | # self.IGDataPath + 'backup/' + self.username + "-" + time.strftime('%Y-%m-%d') + '/' + item['id'] + '.jpg' |
||
1288 | # ) |
||
1289 | go = True |
||
1290 | |||
1291 | if not myUploads.getNextMaxId(): break |
||
1292 | |||
1293 | def follow(self, userId): |
||
1294 | """ |
||
1295 | Follow. |
||
1296 | |||
1297 | :param userId: |
||
1298 | :type userId: str |
||
1299 | :rtype: object |
||
1300 | :return: Friendship status data |
||
1301 | """ |
||
1302 | |||
1303 | data = json.dumps( |
||
1304 | OrderedDict([ |
||
1305 | ('_uuid', self.uuid), |
||
1306 | ('_uid', self.username_id), |
||
1307 | ('user_id', userId), |
||
1308 | ('_csrftoken', self.token) |
||
1309 | |||
1310 | ]) |
||
1311 | ) |
||
1312 | |||
1313 | return self.http.request("friendships/create/" + userId + "/", SignatureUtils.generateSignature(data))[1] |
||
1314 | |||
1315 | def unfollow(self, userId): |
||
1316 | """ |
||
1317 | Unfollow. |
||
1318 | |||
1319 | :param userId: |
||
1320 | :type userId: str |
||
1321 | :rtype: object |
||
1322 | :return: Friendship status data |
||
1323 | """ |
||
1324 | data = json.dumps( |
||
1325 | OrderedDict([ |
||
1326 | ('_uuid', self.uuid), |
||
1327 | ('_uid', self.username_id), |
||
1328 | ('user_id', userId), |
||
1329 | ('_csrftoken', self.token) |
||
1330 | ]) |
||
1331 | ) |
||
1332 | |||
1333 | return self.http.request("friendships/destroy/" + userId + "/", SignatureUtils.generateSignature(data))[1] |
||
1334 | |||
1335 | def block(self, userId): |
||
1336 | """ |
||
1337 | Block. |
||
1338 | |||
1339 | :param userId: |
||
1340 | :type userId: str |
||
1341 | :rtype: object |
||
1342 | :return: Friendship status data |
||
1343 | """ |
||
1344 | |||
1345 | data = json.dumps( |
||
1346 | OrderedDict([ |
||
1347 | ('_uuid', self.uuid), |
||
1348 | ('_uid', self.username_id), |
||
1349 | ('user_id', userId), |
||
1350 | ('_csrftoken', self.token) |
||
1351 | ]) |
||
1352 | ) |
||
1353 | |||
1354 | return self.http.request("friendships/block/" + userId + "/", SignatureUtils.generateSignature(data))[1] |
||
1355 | |||
1356 | def unblock(self, userId): |
||
1357 | """ |
||
1358 | Unblock. |
||
1359 | |||
1360 | :param userId: |
||
1361 | :type userId: str |
||
1362 | :rtype: object |
||
1363 | :return: Friendship status data |
||
1364 | """ |
||
1365 | |||
1366 | data = json.dumps( |
||
1367 | OrderedDict([ |
||
1368 | ('_uuid', self.uuid), |
||
1369 | ('_uid', self.username_id), |
||
1370 | ('user_id', userId), |
||
1371 | ('_csrftoken', self.token) |
||
1372 | ]) |
||
1373 | ) |
||
1374 | |||
1375 | return self.http.request("friendships/unblock/" + userId + "/", SignatureUtils.generateSignature(data))[1] |
||
1376 | |||
1377 | def userFriendship(self, userId): |
||
1378 | """ |
||
1379 | Show User Friendship. |
||
1380 | |||
1381 | :type userId: str |
||
1382 | :param userId: |
||
1383 | :rtype: object |
||
1384 | :return: Friendship relationship data |
||
1385 | """ |
||
1386 | |||
1387 | data = json.dumps( |
||
1388 | OrderedDict([ |
||
1389 | ('_uuid', self.uuid), |
||
1390 | ('_uid', self.username_id), |
||
1391 | ('user_id', userId), |
||
1392 | ('_csrftoken', self.token) |
||
1393 | ]) |
||
1394 | ) |
||
1395 | |||
1396 | return self.http.request("friendships/show/" + userId + "/", SignatureUtils.generateSignature(data))[1] |
||
1397 | |||
1398 | def getLikedMedia(self, maxid=None): |
||
1399 | """ |
||
1400 | Get liked media. |
||
1401 | |||
1402 | :rtype: object |
||
1403 | :return: Liked media data |
||
1404 | """ |
||
1405 | endpoint = 'feed/liked/?' + (('max_id=' + str(maxid) + '&') if maxid is not None else '') |
||
1406 | return self.http.request(endpoint)[1] |
||
1407 | |||
1408 | def verifyPeer(self, enable): |
||
1409 | self.http.verifyPeer(enable) |
||
1410 | |||
1411 | def verifyHost(self, enable): |
||
1412 | self.http.verifyHost(enable) |
||
1413 |