diff --git a/src/InstagramScraper/Instagram.php b/src/InstagramScraper/Instagram.php index 06294910..5107de0e 100644 --- a/src/InstagramScraper/Instagram.php +++ b/src/InstagramScraper/Instagram.php @@ -13,6 +13,8 @@ use InstagramScraper\Model\Story; use InstagramScraper\Model\Tag; use InstagramScraper\Model\UserStories; +use InvalidArgumentException; +use phpFastCache\Cache\ExtendedCacheItemPoolInterface; use phpFastCache\CacheManager; use Unirest\Request; @@ -26,7 +28,9 @@ class Instagram const PAGING_DELAY_MINIMUM_MICROSEC = 1000000; // 1 sec min delay to simulate browser const PAGING_DELAY_MAXIMUM_MICROSEC = 3000000; // 3 sec max delay to simulate browser + /** @var ExtendedCacheItemPoolInterface $instanceCache */ private static $instanceCache; + public $pagingTimeLimitSec = self::PAGING_TIME_LIMIT_SEC; public $pagingDelayMinimumMicrosec = self::PAGING_DELAY_MINIMUM_MICROSEC; public $pagingDelayMaximumMicrosec = self::PAGING_DELAY_MAXIMUM_MICROSEC; @@ -42,6 +46,7 @@ class Instagram * @param null $sessionFolder * * @return Instagram + * @throws \phpFastCache\Exceptions\phpFastCacheDriverCheckException */ public static function withCredentials($username, $password, $sessionFolder = null) { @@ -254,11 +259,9 @@ public function setUserAgent($userAgent) } /** - * @param $userAgent - * * @return null */ - public function resetUserAgent($userAgent) + public function resetUserAgent() { return $this->userAgent = null; } @@ -270,6 +273,7 @@ public function resetUserAgent($userAgent) * * @return Media[] * @throws InstagramException + * @throws InstagramNotFoundException */ public function getMedias($username, $count = 20, $maxId = '') { @@ -295,39 +299,37 @@ public function getAccount($username) throw new InstagramException('Response code is ' . $response->code . '. Body: ' . static::getErrorBody($response->body) . ' Something went wrong. Please report issue.'); } - preg_match_all('#\_sharedData \= (.*?)\;\<\/script\>#', $response->raw_body, $out); - $userArray = json_decode($out[1][0], true, 512, JSON_BIGINT_AS_STRING); - + $userArray = self::extractSharedDataFromBody($response->raw_body); + if (!isset($userArray['entry_data']['ProfilePage'][0]['graphql']['user'])) { throw new InstagramNotFoundException('Account with this username does not exist', 404); } return Account::create($userArray['entry_data']['ProfilePage'][0]['graphql']['user']); } - private function getSharedDataFromPage($url = Endpoints::BASE_URL) - { - $response = Request::get(rtrim($url, '/') . '/', $this->generateHeaders($this->userSession)); - if (static::HTTP_NOT_FOUND === $response->code) { - throw new InstagramNotFoundException('Account with given username does not exist.'); - } - if (static::HTTP_OK !== $response->code) { - throw new InstagramException('Response code is ' . $response->code . '. Body: ' . static::getErrorBody($response->body) . ' Something went wrong. Please report issue.'); - } - - preg_match_all('#\_sharedData \= (.*?)\;\<\/script\>#', $response->raw_body, $out); - return json_decode($out[1][0], true, 512, JSON_BIGINT_AS_STRING); - } - + /** + * @return null + * @throws InstagramException + */ private function getRhxGis() { if ($this->rhxGis === null) { - $sharedData = $this->getSharedDataFromPage(); - $this->rhxGis = $sharedData['rhx_gis']; + try { + $sharedData = $this->getSharedDataFromPage(); + $this->rhxGis = $sharedData['rhx_gis']; + } catch (\Exception $exception) { + throw new InstagramException('Could not extract gis from page'); + } } return $this->rhxGis; } + /** + * @param $variables + * @return string + * @throws InstagramException + */ private function generateGisToken($variables) { return md5(implode(':', [$this->getRhxGis(), $variables ])); @@ -358,7 +360,9 @@ public function getMediasByUserId($id, $count = 12, $maxId = '') if (static::HTTP_OK !== $response->code) { throw new InstagramException('Response code is ' . $response->code . '. Body: ' . static::getErrorBody($response->body) . ' Something went wrong. Please report issue.'); } + $arr = json_decode($response->raw_body, true, 512, JSON_BIGINT_AS_STRING); + if (!is_array($arr)) { throw new InstagramException('Response code is ' . $response->code . '. Body: ' . static::getErrorBody($response->body) . ' Something went wrong. Please report issue.'); } @@ -422,12 +426,14 @@ public function getMediasFromFeed($username, $count = 20) } return $medias; - } - + } + /** * @param $mediaId * * @return Media + * @throws InstagramException + * @throws InstagramNotFoundException */ public function getMediaById($mediaId) { @@ -445,7 +451,7 @@ public function getMediaById($mediaId) public function getMediaByUrl($mediaUrl) { if (filter_var($mediaUrl, FILTER_VALIDATE_URL) === false) { - throw new \InvalidArgumentException('Malformed media url'); + throw new InvalidArgumentException('Malformed media url'); } $response = Request::get(rtrim($mediaUrl, '/') . '/?__a=1', $this->generateHeaders($this->userSession)); // use a raw constant in the code is not a good idea!! @@ -548,11 +554,12 @@ public function getPaginateMedias($username, $maxId = '') } /** - * @param $mediaId + * @param $mediaId * @param int $count * @param null $maxId * * @return Comment[] + * @throws InstagramException */ public function getMediaCommentsById($mediaId, $count = 10, $maxId = null) { @@ -713,7 +720,8 @@ public function getMediaLikesByCode($code, $count = 10, $maxId = null) * * @return Account * @throws InstagramException - * @throws \InvalidArgumentException + * @throws InvalidArgumentException + * @throws InstagramNotFoundException */ public function getAccountById($id) { @@ -1258,6 +1266,12 @@ public function isLoggedIn($session) return true; } + /** + * @param $response + * @param $cookies + * @return \Unirest\Response + * @throws InstagramAuthException + */ private function verifyTwoStep($response, $cookies) { $new_cookies = static::parseCookies($response->headers['Set-Cookie']); @@ -1347,4 +1361,33 @@ public function saveSession() $cachedString = static::$instanceCache->getItem($this->sessionUsername); $cachedString->set($this->userSession); } + + private static function extractSharedDataFromBody($body) + { + if (preg_match_all('#\_sharedData \= (.*?)\;\<\/script\>#', $body, $out)) { + return json_decode($out[1][0], true, 512, JSON_BIGINT_AS_STRING); + } + + return null; + } + + /** + * @param string $url + * @return mixed|null + * @throws InstagramException + * @throws InstagramNotFoundException + */ + private function getSharedDataFromPage($url = Endpoints::BASE_URL) + { + $response = Request::get(rtrim($url, '/') . '/', $this->generateHeaders($this->userSession)); + if (static::HTTP_NOT_FOUND === $response->code) { + throw new InstagramNotFoundException("Page {$url} not found"); + } + + if (static::HTTP_OK !== $response->code) { + throw new InstagramException('Response code is ' . $response->code . '. Body: ' . static::getErrorBody($response->body) . ' Something went wrong. Please report issue.'); + } + + return self::extractSharedDataFromBody($response->raw_body); + } }