Advertisement
Guest User

Untitled

a guest
Sep 20th, 2017
1,507
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 30.32 KB | None | 0 0
  1. <?php
  2.  
  3. namespace InstagramAPI;
  4.  
  5. /**
  6. * Instagram's Private API v3.
  7. *
  8. * TERMS OF USE:
  9. * - This code is in no way affiliated with, authorized, maintained, sponsored
  10. * or endorsed by Instagram or any of its affiliates or subsidiaries. This is
  11. * an independent and unofficial API. Use at your own risk.
  12. * - We do NOT support or tolerate anyone who wants to use this API to send spam
  13. * or commit other online crimes.
  14. * - You will NOT use this API for marketing or other abusive purposes (spam,
  15. * botting, harassment, massive bulk messaging...).
  16. *
  17. * @author mgp25: Founder, Reversing, Project Leader (https://github.com/mgp25)
  18. * @author SteveJobzniak (https://github.com/SteveJobzniak)
  19. */
  20. class Instagram
  21. {
  22. /**
  23. * Experiments refresh interval in sec.
  24. *
  25. * @var int
  26. */
  27. const EXPERIMENTS_REFRESH = 7200;
  28.  
  29. /**
  30. * Currently active Instagram username.
  31. *
  32. * @var string
  33. */
  34. public $username;
  35.  
  36. /**
  37. * Currently active Instagram password.
  38. *
  39. * @var string
  40. */
  41. public $password;
  42.  
  43. /**
  44. * The Android Device for the currently active user.
  45. *
  46. * @var \InstagramAPI\Devices\Device
  47. */
  48. public $device;
  49.  
  50. /**
  51. * Toggles API query/response debug output.
  52. *
  53. * @var bool
  54. */
  55. public $debug;
  56.  
  57. /**
  58. * Toggles truncating long responses when debugging.
  59. *
  60. * @var bool
  61. */
  62. public $truncatedDebug;
  63.  
  64. /**
  65. * For internal use by Instagram-API developers!
  66. *
  67. * Toggles the throwing of exceptions whenever Instagram-API's "Response"
  68. * classes lack fields that were provided by the server. Useful for
  69. * discovering that our library classes need updating.
  70. *
  71. * This is only settable via this public property and is NOT meant for
  72. * end-users of this library. It is for contributing developers!
  73. *
  74. * @var bool
  75. */
  76. public $apiDeveloperDebug = false;
  77.  
  78. /**
  79. * UUID.
  80. *
  81. * @var string
  82. */
  83. public $uuid;
  84.  
  85. /**
  86. * Google Play Advertising ID.
  87. *
  88. * The advertising ID is a unique ID for advertising, provided by Google
  89. * Play services for use in Google Play apps. Used by Instagram.
  90. *
  91. * @var string
  92. *
  93. * @see https://support.google.com/googleplay/android-developer/answer/6048248?hl=en
  94. */
  95. public $advertising_id;
  96.  
  97. /**
  98. * Device ID.
  99. *
  100. * @var string
  101. */
  102. public $device_id;
  103.  
  104. /**
  105. * Phone ID.
  106. *
  107. * @var string
  108. */
  109. public $phone_id;
  110.  
  111. /**
  112. * Numerical UserPK ID of the active user account.
  113. *
  114. * @var string
  115. */
  116. public $account_id;
  117.  
  118. /**
  119. * Session status.
  120. *
  121. * @var bool
  122. */
  123. public $isLoggedIn = false;
  124.  
  125. /**
  126. * Rank token.
  127. *
  128. * @var string
  129. */
  130. public $rank_token;
  131.  
  132. /**
  133. * Raw API communication/networking class.
  134. *
  135. * @var Client
  136. */
  137. public $client;
  138.  
  139. /**
  140. * The account settings storage.
  141. *
  142. * @var \InstagramAPI\Settings\StorageHandler|null
  143. */
  144. public $settings;
  145.  
  146. /**
  147. * The current application session ID.
  148. *
  149. * This is a temporary ID which changes in the official app every time the
  150. * user closes and re-opens the Instagram application or switches account.
  151. *
  152. * @var string
  153. */
  154. public $session_id;
  155.  
  156. /**
  157. * A list of experiments enabled on per-account basis.
  158. *
  159. * @var array
  160. */
  161. public $experiments;
  162.  
  163. /** @var Request\Account Collection of Account related functions. */
  164. public $account;
  165. /** @var Request\Business Collection of Business related functions. */
  166. public $business;
  167. /** @var Request\Collection Collection of Collections related functions. */
  168. public $collection;
  169. /** @var Request\Creative Collection of Creative related functions. */
  170. public $creative;
  171. /** @var Request\Direct Collection of Direct related functions. */
  172. public $direct;
  173. /** @var Request\Discover Collection of Discover related functions. */
  174. public $discover;
  175. /** @var Request\Hashtag Collection of Hashtag related functions. */
  176. public $hashtag;
  177. /** @var Request\Internal Collection of Internal (non-public) functions. */
  178. public $internal;
  179. /** @var Request\Live Collection of Live related functions. */
  180. public $live;
  181. /** @var Request\Location Collection of Location related functions. */
  182. public $location;
  183. /** @var Request\Media Collection of Media related functions. */
  184. public $media;
  185. /** @var Request\People Collection of People related functions. */
  186. public $people;
  187. /** @var Request\Push Collection of Push related functions. */
  188. public $push;
  189. /** @var Request\Story Collection of Story related functions. */
  190. public $story;
  191. /** @var Request\Timeline Collection of Timeline related functions. */
  192. public $timeline;
  193. /** @var Request\Usertag Collection of Usertag related functions. */
  194. public $usertag;
  195.  
  196. /**
  197. * Constructor.
  198. *
  199. * @param bool $debug Show API queries and responses.
  200. * @param bool $truncatedDebug Truncate long responses in debug.
  201. * @param array $storageConfig Configuration for the desired
  202. * user settings storage backend.
  203. *
  204. * @throws \InstagramAPI\Exception\InstagramException
  205. */
  206. public function __construct(
  207. $debug = false,
  208. $truncatedDebug = false,
  209. $storageConfig = [])
  210. {
  211. // Prevent people from running this library on ancient PHP versions.
  212. if (!defined('PHP_VERSION_ID')) { // Emulate version value if missing.
  213. $version = explode('.', PHP_VERSION);
  214. define('PHP_VERSION_ID', ($version[0] * 10000 + $version[1] * 100 + $version[2]));
  215. }
  216. if (PHP_VERSION_ID < 50600) {
  217. throw new \InstagramAPI\Exception\InternalException('You must have PHP 5.6 or higher to use the Instagram API library.');
  218. }
  219.  
  220. // Debugging options.
  221. $this->debug = $debug;
  222. $this->truncatedDebug = $truncatedDebug;
  223.  
  224. // Load all function collections.
  225. $this->account = new Request\Account($this);
  226. $this->business = new Request\Business($this);
  227. $this->collection = new Request\Collection($this);
  228. $this->creative = new Request\Creative($this);
  229. $this->direct = new Request\Direct($this);
  230. $this->discover = new Request\Discover($this);
  231. $this->hashtag = new Request\Hashtag($this);
  232. $this->internal = new Request\Internal($this);
  233. $this->live = new Request\Live($this);
  234. $this->location = new Request\Location($this);
  235. $this->media = new Request\Media($this);
  236. $this->people = new Request\People($this);
  237. $this->push = new Request\Push($this);
  238. $this->story = new Request\Story($this);
  239. $this->timeline = new Request\Timeline($this);
  240. $this->usertag = new Request\Usertag($this);
  241.  
  242. // Configure the settings storage and network client.
  243. $self = $this;
  244. $this->settings = Settings\Factory::createHandler(
  245. $storageConfig,
  246. [
  247. // This saves all user session cookies "in bulk" at script exit
  248. // or when switching to a different user, so that it only needs
  249. // to write cookies to storage a few times per user session:
  250. 'onCloseUser' => function ($storage) use ($self) {
  251. if ($self->client instanceof Client) {
  252. $self->client->saveCookieJar();
  253. }
  254. },
  255. ]
  256. );
  257. $this->client = new Client($this);
  258. $this->experiments = [];
  259. }
  260.  
  261. /**
  262. * Controls the SSL verification behavior of the Client.
  263. *
  264. * @see http://docs.guzzlephp.org/en/latest/request-options.html#verify
  265. *
  266. * @param bool|string $state TRUE to verify using PHP's default CA bundle,
  267. * FALSE to disable SSL verification (this is
  268. * insecure!), String to verify using this path to
  269. * a custom CA bundle file.
  270. */
  271. public function setVerifySSL(
  272. $state)
  273. {
  274. $this->client->setVerifySSL($state);
  275. }
  276.  
  277. /**
  278. * Gets the current SSL verification behavior of the Client.
  279. *
  280. * @return bool|string
  281. */
  282. public function getVerifySSL()
  283. {
  284. return $this->client->getVerifySSL();
  285. }
  286.  
  287. /**
  288. * Set the proxy to use for requests.
  289. *
  290. * @see http://docs.guzzlephp.org/en/latest/request-options.html#proxy
  291. *
  292. * @param string|array|null $value String or Array specifying a proxy in
  293. * Guzzle format, or NULL to disable proxying.
  294. */
  295. public function setProxy(
  296. $value)
  297. {
  298. $this->client->setProxy($value);
  299. }
  300.  
  301. /**
  302. * Gets the current proxy used for requests.
  303. *
  304. * @return string|array|null
  305. */
  306. public function getProxy()
  307. {
  308. return $this->client->getProxy();
  309. }
  310.  
  311. /**
  312. * Sets the network interface override to use.
  313. *
  314. * Only works if Guzzle is using the cURL backend. But that's
  315. * almost always the case, on most PHP installations.
  316. *
  317. * @see http://php.net/curl_setopt CURLOPT_INTERFACE
  318. *
  319. * @param string|null $value Interface name, IP address or hostname, or NULL to
  320. * disable override and let Guzzle use any interface.
  321. */
  322. public function setOutputInterface(
  323. $value)
  324. {
  325. $this->client->setOutputInterface($value);
  326. }
  327.  
  328. /**
  329. * Gets the current network interface override used for requests.
  330. *
  331. * @return string|null
  332. */
  333. public function getOutputInterface()
  334. {
  335. return $this->client->getOutputInterface();
  336. }
  337.  
  338. /**
  339. * Login to Instagram or automatically resume and refresh previous session.
  340. *
  341. * Sets the active account for the class instance. You can call this multiple times to switch
  342. * between multiple Instagram accounts.
  343. *
  344. * WARNING: You MUST run this function EVERY time your script runs! It handles automatic session
  345. * resume and relogin and app session state refresh and other absolutely *vital* things that are
  346. * important if you don't want to be banned from Instagram!
  347. *
  348. * WARNING: This function MAY return a CHALLENGE telling you that the account needs two-factor
  349. * login before letting you log in! Read the two-factor login example to see how to handle that.
  350. *
  351. * @param string $username Your Instagram username.
  352. * @param string $password Your Instagram password.
  353. * @param bool $forceLogin Force login to Instagram instead of resuming previous session.
  354. * @param int $appRefreshInterval How frequently login() should act like an Instagram app
  355. * that's been closed and reopened and needs to "refresh its
  356. * state", by asking for extended account state details.
  357. * Default: After 1800 seconds, meaning 30 minutes since the
  358. * last state-refreshing login() call.
  359. * This CANNOT be longer than 6 hours. Read _sendLoginFlow()!
  360. * The shorter your delay is the BETTER. You may even want to
  361. * set it to an even LOWER value than the default 30 minutes!
  362. *
  363. * @throws \InvalidArgumentException
  364. * @throws \InstagramAPI\Exception\InstagramException
  365. *
  366. * @return \InstagramAPI\Response\LoginResponse|null A login response if a full (re-)login happens,
  367. * otherwise NULL if an existing session is resumed.
  368. */
  369. public function login(
  370. $username,
  371. $password,
  372. $forceLogin = false,
  373. $appRefreshInterval = 1800)
  374. {
  375. if (empty($username) || empty($password)) {
  376. throw new \InvalidArgumentException('You must provide a username and password to login().');
  377. }
  378.  
  379. // Switch the currently active user/pass if the details are different.
  380. if ($this->username !== $username || $this->password !== $password) {
  381. $this->_setUser($username, $password);
  382. }
  383.  
  384. // Perform a full relogin if necessary.
  385. if (!$this->isLoggedIn || $forceLogin) {
  386. $this->_sendPreLoginFlow();
  387.  
  388. try {
  389. $response = $this->request('accounts/login/')
  390. ->setNeedsAuth(false)
  391. ->addPost('phone_id', $this->phone_id)
  392. ->addPost('_csrftoken', $this->client->getToken())
  393. ->addPost('username', $this->username)
  394. ->addPost('adid', $this->advertising_id)
  395. ->addPost('guid', $this->uuid)
  396. ->addPost('device_id', $this->device_id)
  397. ->addPost('password', $this->password)
  398. ->addPost('login_attempt_count', 0)
  399. ->getResponse(new Response\LoginResponse());
  400. } catch (\InstagramAPI\Exception\InstagramException $e) {
  401. if ($e->hasResponse() && $e->getResponse()->isTwoFactorRequired()) {
  402. // Login failed because two-factor login is required.
  403. // Return server response to tell user they need 2-factor.
  404. return $e->getResponse();
  405. } else {
  406. // Login failed for some other reason... Re-throw error.
  407. throw $e;
  408. }
  409. }
  410.  
  411. $this->_updateLoginState($response);
  412.  
  413. $this->_sendLoginFlow(true, $appRefreshInterval);
  414.  
  415. // Full (re-)login successfully completed. Return server response.
  416. return $response;
  417. }
  418.  
  419. // Attempt to resume an existing session, or full re-login if necessary.
  420. // NOTE: The "return" here gives a LoginResponse in case of re-login.
  421. return $this->_sendLoginFlow(false, $appRefreshInterval);
  422. }
  423.  
  424. /**
  425. * Finish a two-factor authenticated login.
  426. *
  427. * This function finishes a two-factor challenge that was provided by the
  428. * regular login() function. If you successfully answer their challenge,
  429. * you will be logged in after this function call.
  430. *
  431. * @param string $verificationCode Verification code you have received via SMS.
  432. * @param string $twoFactorIdentifier Two factor identifier, obtained in login() response. Format: "123456".
  433. * @param int $appRefreshInterval See login() for description of this parameter.
  434. *
  435. * @throws \InstagramAPI\Exception\InstagramException
  436. *
  437. * @return \InstagramAPI\Response\LoginResponse
  438. */
  439. public function finishTwoFactorLogin(
  440. $verificationCode,
  441. $twoFactorIdentifier,
  442. $appRefreshInterval = 1800)
  443. {
  444. if (empty($this->username) || empty($this->password)) {
  445. throw new \InstagramAPI\Exception\LoginRequiredException(
  446. 'You must provide a username and password to login() before attempting to finish the two-factor login process.'
  447. );
  448. }
  449.  
  450. $verificationCode = trim(str_replace(' ', '', $verificationCode));
  451.  
  452. $response = $this->request('accounts/two_factor_login/')
  453. ->setNeedsAuth(false)
  454. ->addPost('verification_code', $verificationCode)
  455. ->addPost('two_factor_identifier', $twoFactorIdentifier)
  456. ->addPost('_csrftoken', $this->client->getToken())
  457. ->addPost('username', $this->username)
  458. ->addPost('device_id', $this->device_id)
  459. ->addPost('password', $this->password)
  460. ->getResponse(new Response\LoginResponse());
  461.  
  462. $this->_updateLoginState($response);
  463.  
  464. $this->_sendLoginFlow(true, $appRefreshInterval);
  465.  
  466. return $response;
  467. }
  468.  
  469. /**
  470. * Set the active account for the class instance.
  471. *
  472. * We can call this multiple times to switch between multiple accounts.
  473. *
  474. * @param string $username Your Instagram username.
  475. * @param string $password Your Instagram password.
  476. *
  477. * @throws \InvalidArgumentException
  478. * @throws \InstagramAPI\Exception\InstagramException
  479. */
  480. protected function _setUser(
  481. $username,
  482. $password)
  483. {
  484. if (empty($username) || empty($password)) {
  485. throw new \InvalidArgumentException('You must provide a username and password to _setUser().');
  486. }
  487.  
  488. // Load all settings from the storage and mark as current user.
  489. $this->settings->setActiveUser($username);
  490.  
  491. // Generate the user's Device instance, which will be created from the
  492. // user's last-used device IF they've got a valid, good one stored.
  493. // But if they've got a BAD/none, this will create a brand-new device.
  494. $savedDeviceString = $this->settings->get('devicestring');
  495. $this->device = new Devices\Device(Constants::IG_VERSION, Constants::VERSION_CODE, Constants::USER_AGENT_LOCALE, $savedDeviceString);
  496.  
  497. // Get active device string so that we can compare it to any saved one.
  498. $deviceString = $this->device->getDeviceString();
  499.  
  500. // Generate a brand-new device fingerprint if the Device wasn't reused
  501. // from settings, OR if any of the stored fingerprints are missing.
  502. // NOTE: The regeneration when our device model changes is to avoid
  503. // dangerously reusing the "previous phone's" unique hardware IDs.
  504. // WARNING TO CONTRIBUTORS: Only add new parameter-checks here if they
  505. // are CRITICALLY important to the particular device. We don't want to
  506. // frivolously force the users to generate new device IDs constantly.
  507. $resetCookieJar = false;
  508. if ($deviceString !== $savedDeviceString // Brand new device, or missing
  509. || empty($this->settings->get('uuid')) // one of the critically...
  510. || empty($this->settings->get('phone_id')) // ...important device...
  511. || empty($this->settings->get('device_id'))) { // ...parameters.
  512. // Erase all previously stored device-specific settings.
  513. $this->settings->eraseDeviceSettings();
  514.  
  515. // Save the chosen device string to settings.
  516. $this->settings->set('devicestring', $deviceString);
  517.  
  518. // Generate hardware fingerprints for the new device.
  519. $this->settings->set('device_id', Signatures::generateDeviceId());
  520. $this->settings->set('phone_id', Signatures::generateUUID(true));
  521. $this->settings->set('uuid', Signatures::generateUUID(true));
  522.  
  523. // Erase any stored account ID, to ensure that we detect ourselves
  524. // as logged-out. This will force a new relogin from the new device.
  525. $this->settings->set('account_id', '');
  526.  
  527. // We'll also need to throw out all previous cookies.
  528. $resetCookieJar = true;
  529. }
  530.  
  531. // Generate other missing values. These are for less critical parameters
  532. // that don't need to trigger a complete device reset like above. For
  533. // example, this is good for new parameters that Instagram introduces
  534. // over time, since those can be added one-by-one over time here without
  535. // needing to wipe/reset the whole device.
  536. if (empty($this->settings->get('advertising_id'))) {
  537. $this->settings->set('advertising_id', Signatures::generateUUID(true));
  538. }
  539. if (empty($this->settings->get('session_id'))) {
  540. $this->settings->set('session_id', Signatures::generateUUID(true));
  541. }
  542.  
  543. // Store various important parameters for easy access.
  544. $this->username = $username;
  545. $this->password = $password;
  546. $this->uuid = $this->settings->get('uuid');
  547. $this->advertising_id = $this->settings->get('advertising_id');
  548. $this->device_id = $this->settings->get('device_id');
  549. $this->phone_id = $this->settings->get('phone_id');
  550. $this->session_id = $this->settings->get('session_id');
  551. $this->experiments = $this->settings->getExperiments();
  552.  
  553. // Load the previous session details if we're possibly logged in.
  554. if (!$resetCookieJar && $this->settings->isMaybeLoggedIn()) {
  555. $this->isLoggedIn = true;
  556. $this->account_id = $this->settings->get('account_id');
  557. $this->rank_token = $this->account_id.'_'.$this->uuid;
  558. } else {
  559. $this->isLoggedIn = false;
  560. $this->account_id = null;
  561. $this->rank_token = null;
  562. }
  563.  
  564. // Configures Client for current user AND updates isLoggedIn state
  565. // if it fails to load the expected cookies from the user's jar.
  566. // Must be done last here, so that isLoggedIn is properly updated!
  567. // NOTE: If we generated a new device we start a new cookie jar.
  568. $this->client->updateFromCurrentSettings($resetCookieJar);
  569. }
  570.  
  571. /**
  572. * Updates the internal state after a successful login.
  573. *
  574. * @param Response\LoginResponse $response The login response.
  575. *
  576. * @throws \InvalidArgumentException
  577. * @throws \InstagramAPI\Exception\InstagramException
  578. */
  579. protected function _updateLoginState(
  580. Response\LoginResponse $response)
  581. {
  582. // This check is just protection against accidental bugs. It makes sure
  583. // that we always call this function with a *successful* login response!
  584. if (!$response instanceof Response\LoginResponse
  585. || !$response->isOk()) {
  586. throw new \InvalidArgumentException('Invalid login response provided to _updateLoginState().');
  587. }
  588.  
  589. $this->isLoggedIn = true;
  590. $this->account_id = $response->getLoggedInUser()->getPk();
  591. $this->settings->set('account_id', $this->account_id);
  592. $this->rank_token = $this->account_id.'_'.$this->uuid;
  593. $this->settings->set('last_login', time());
  594. }
  595.  
  596. /**
  597. * Sends pre-login flow. This is required to emulate real device behavior.
  598. *
  599. * @throws \InstagramAPI\Exception\InstagramException
  600. */
  601. protected function _sendPreLoginFlow()
  602. {
  603. // Calling this non-token API will put a csrftoken in our cookie
  604. // jar. We must do this before any functions that require a token.
  605. $this->internal->syncDeviceFeatures(true);
  606. $this->internal->readMsisdnHeader();
  607. $this->internal->logAttribution();
  608. }
  609.  
  610. /**
  611. * Sends login flow. This is required to emulate real device behavior.
  612. *
  613. * @param bool $justLoggedIn
  614. * @param int $appRefreshInterval
  615. *
  616. * @throws \InvalidArgumentException
  617. * @throws \InstagramAPI\Exception\InstagramException
  618. *
  619. * @return \InstagramAPI\Response\LoginResponse|null A login response if a full (re-)login is needed
  620. * during the login flow attempt, otherwise NULL.
  621. */
  622. protected function _sendLoginFlow(
  623. $justLoggedIn,
  624. $appRefreshInterval = 1800)
  625. {
  626. if ($appRefreshInterval > 21600) {
  627. throw new \InvalidArgumentException("Instagram's app state refresh interval is NOT allowed to be higher than 6 hours, and the lower the better!");
  628. }
  629.  
  630. // SUPER IMPORTANT:
  631. //
  632. // STOP trying to ask us to remove this code section!
  633. //
  634. // EVERY time the user presses their device's home button to leave the
  635. // app and then comes back to the app, Instagram does ALL of these things
  636. // to refresh its internal app state. We MUST emulate that perfectly,
  637. // otherwise Instagram will silently detect you as a "fake" client
  638. // after a while!
  639. //
  640. // You can configure the login's $appRefreshInterval in the function
  641. // parameter above, but you should keep it VERY frequent (definitely
  642. // NEVER longer than 6 hours), so that Instagram sees you as a real
  643. // client that keeps quitting and opening their app like a REAL user!
  644. //
  645. // Otherwise they WILL detect you as a bot and silently BLOCK features
  646. // or even ban you.
  647. //
  648. // You have been warned.
  649. if ($justLoggedIn) {
  650. // Perform the "user has just done a full login" API flow.
  651. $this->people->getAutoCompleteUserList();
  652. $this->story->getReelsTrayFeed();
  653. $this->timeline->getTimelineFeed();
  654. $this->direct->getRecentRecipients();
  655. $this->internal->syncUserFeatures();
  656. //$this->push->register();
  657. $this->direct->getRankedRecipients('reshare', true);
  658. $this->direct->getRankedRecipients('raven', true);
  659. $this->direct->getInbox();
  660. $this->direct->getVisualInbox();
  661. // bootstrap users
  662. $this->internal->getProfileNotice();
  663. //$this->internal->getMegaphoneLog();
  664. $this->people->getRecentActivityInbox();
  665. $this->internal->getQPFetch();
  666. $this->media->getBlockedMedia();
  667. $this->discover->getExploreFeed(null, true);
  668. //$this->internal->getFacebookOTA();
  669. } else {
  670. // Act like a real logged in app client refreshing its news timeline.
  671. // This also lets us detect if we're still logged in with a valid session.
  672. try {
  673. $this->timeline->getTimelineFeed(null, [
  674. 'is_pull_to_refresh' => mt_rand(1, 3) < 3,
  675. ]);
  676. } catch (\InstagramAPI\Exception\LoginRequiredException $e) {
  677. // If our session cookies are expired, we were now told to login,
  678. // so handle that by running a forced relogin in that case!
  679. return $this->login($this->username, $this->password, true, $appRefreshInterval);
  680. }
  681.  
  682. // Perform the "user has returned to their already-logged in app,
  683. // so refresh all feeds to check for news" API flow.
  684. $lastLoginTime = $this->settings->get('last_login');
  685. if (is_null($lastLoginTime) || (time() - $lastLoginTime) > $appRefreshInterval) {
  686. $this->settings->set('last_login', time());
  687.  
  688. // Generate and save a new application session ID.
  689. $this->session_id = Signatures::generateUUID(true);
  690. $this->settings->set('session_id', $this->session_id);
  691.  
  692. // Do the rest of the "user is re-opening the app" API flow...
  693. $this->people->getAutoCompleteUserList();
  694. $this->story->getReelsTrayFeed();
  695. $this->direct->getRankedRecipients('reshare', true);
  696. $this->direct->getRankedRecipients('raven', true);
  697. //push register
  698. $this->direct->getRecentRecipients();
  699. //push register
  700. //$this->internal->getMegaphoneLog();
  701. $this->direct->getInbox();
  702. $this->people->getRecentActivityInbox();
  703. $this->internal->getProfileNotice();
  704. $this->discover->getExploreFeed();
  705. }
  706.  
  707. // Users normally resume their sessions, meaning that their
  708. // experiments never get synced and updated. So sync periodically.
  709. $lastExperimentsTime = $this->settings->get('last_experiments');
  710. if (is_null($lastExperimentsTime) || (time() - $lastExperimentsTime) > self::EXPERIMENTS_REFRESH) {
  711. $this->internal->syncUserFeatures();
  712. $this->internal->syncDeviceFeatures();
  713. }
  714. }
  715.  
  716. // We've now performed a login or resumed a session. Forcibly write our
  717. // cookies to the storage, to ensure that the storage doesn't miss them
  718. // in case something bad happens to PHP after this moment.
  719. $this->client->saveCookieJar();
  720. }
  721.  
  722. /**
  723. * Log out of Instagram.
  724. *
  725. * WARNING: Most people should NEVER call logout()! Our library emulates
  726. * the Instagram app for Android, where you are supposed to stay logged in
  727. * forever. By calling this function, you will tell Instagram that you are
  728. * logging out of the APP. But you SHOULDN'T do that! In almost 100% of all
  729. * cases you want to *stay logged in* so that LOGIN() resumes your session!
  730. *
  731. * @throws \InstagramAPI\Exception\InstagramException
  732. *
  733. * @return \InstagramAPI\Response\LogoutResponse
  734. *
  735. * @see Instagram::login()
  736. */
  737. public function logout()
  738. {
  739. $response = $this->request('accounts/logout/')
  740. ->addPost('phone_id', $this->phone_id)
  741. ->addPost('_csrftoken', $this->client->getToken())
  742. ->addPost('guid', $this->uuid)
  743. ->addPost('device_id', $this->device_id)
  744. ->addPost('_uuid', $this->uuid)
  745. ->getResponse(new Response\LogoutResponse());
  746.  
  747. // We've now logged out. Forcibly write our cookies to the storage, to
  748. // ensure that the storage doesn't miss them in case something bad
  749. // happens to PHP after this moment.
  750. $this->client->saveCookieJar();
  751.  
  752. return $response;
  753. }
  754.  
  755. /**
  756. * Checks if a parameter is enabled in the given experiment.
  757. *
  758. * @param string $experiment
  759. * @param string $param
  760. *
  761. * @return bool
  762. */
  763. public function isExperimentEnabled(
  764. $experiment,
  765. $param)
  766. {
  767. return isset($this->experiments[$experiment][$param])
  768. && in_array($this->experiments[$experiment][$param], ['enabled', 'true', '1']);
  769. }
  770.  
  771. /**
  772. * Create a custom API request.
  773. *
  774. * Used internally, but can also be used by end-users if they want
  775. * to create completely custom API queries without modifying this library.
  776. *
  777. * @param string $url
  778. *
  779. * @return \InstagramAPI\Request
  780. */
  781. public function request(
  782. $url)
  783. {
  784. return new Request($this, $url);
  785. }
  786. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement