From 6a70c243f7de8772ae5a176e388bbac812d7cd5e Mon Sep 17 00:00:00 2001 From: Alexandr Date: Sat, 7 Apr 2018 17:07:38 +0700 Subject: [PATCH] v1.2.5 --- classes/InWidget/API/apiModel.php | 1 - classes/InWidget/API/apiOfficial.php | 1 - classes/InWidget/API/apiScraper.php | 1 - classes/InWidget/Core.php | 1 - .../InWidget/Exception/inWidgetException.php | 1 - classes/InstagramScraper/Endpoints.php | 10 +- classes/InstagramScraper/Instagram.php | 250 ++-- classes/InstagramScraper/Model/Account.php | 25 +- classes/InstagramScraper/Model/Media.php | 1206 ++++++++--------- index.php | 3 +- langs/en.php | 1 - langs/ru.php | 1 - langs/ua.php | 1 - readme.txt | 10 +- template.php | 1 - 15 files changed, 735 insertions(+), 778 deletions(-) diff --git a/classes/InWidget/API/apiModel.php b/classes/InWidget/API/apiModel.php index 8f255de..bc7acf7 100644 --- a/classes/InWidget/API/apiModel.php +++ b/classes/InWidget/API/apiModel.php @@ -13,7 +13,6 @@ * @link http://inwidget.ru * @copyright 2014-2018 Alexandr Kazarmshchikov * @author Alexandr Kazarmshchikov - * @version 1.2.4 * @package inWidget\API * */ diff --git a/classes/InWidget/API/apiOfficial.php b/classes/InWidget/API/apiOfficial.php index 62241f0..37e1942 100644 --- a/classes/InWidget/API/apiOfficial.php +++ b/classes/InWidget/API/apiOfficial.php @@ -15,7 +15,6 @@ * @link http://inwidget.ru * @copyright 2014-2018 Alexandr Kazarmshchikov * @author Alexandr Kazarmshchikov - * @version 1.2.4 * @package inWidget\API * */ diff --git a/classes/InWidget/API/apiScraper.php b/classes/InWidget/API/apiScraper.php index d9a560b..3a30766 100644 --- a/classes/InWidget/API/apiScraper.php +++ b/classes/InWidget/API/apiScraper.php @@ -13,7 +13,6 @@ * @link http://inwidget.ru * @copyright 2014-2018 Alexandr Kazarmshchikov * @author Alexandr Kazarmshchikov - * @version 1.2.4 * @package inWidget\API * */ diff --git a/classes/InWidget/Core.php b/classes/InWidget/Core.php index 75cec46..44e5ed1 100644 --- a/classes/InWidget/Core.php +++ b/classes/InWidget/Core.php @@ -16,7 +16,6 @@ * @link http://inwidget.ru * @copyright 2014-2018 Alexandr Kazarmshchikov * @author Alexandr Kazarmshchikov - * @version 1.2.4 * @package inWidget * */ diff --git a/classes/InWidget/Exception/inWidgetException.php b/classes/InWidget/Exception/inWidgetException.php index e586a8d..105a95f 100644 --- a/classes/InWidget/Exception/inWidgetException.php +++ b/classes/InWidget/Exception/inWidgetException.php @@ -13,7 +13,6 @@ * @link http://inwidget.ru * @copyright 2014-2018 Alexandr Kazarmshchikov * @author Alexandr Kazarmshchikov - * @version 1.2.4 * @package inWidget * */ diff --git a/classes/InstagramScraper/Endpoints.php b/classes/InstagramScraper/Endpoints.php index fdd76fd..75fe632 100644 --- a/classes/InstagramScraper/Endpoints.php +++ b/classes/InstagramScraper/Endpoints.php @@ -8,11 +8,11 @@ class Endpoints const LOGIN_URL = 'https://www.instagram.com/accounts/login/ajax/'; const ACCOUNT_PAGE = 'https://www.instagram.com/{username}'; const MEDIA_LINK = 'https://www.instagram.com/p/{code}'; - const ACCOUNT_MEDIAS = 'https://instagram.com/graphql/query/?query_id=17888483320059182&id={user_id}&first=30&after={max_id}'; + const ACCOUNT_MEDIAS = 'https://www.instagram.com/{username}/?__a=1&max_id={max_id}'; const ACCOUNT_JSON_INFO = 'https://www.instagram.com/{username}/?__a=1'; const MEDIA_JSON_INFO = 'https://www.instagram.com/p/{code}/?__a=1'; const MEDIA_JSON_BY_LOCATION_ID = 'https://www.instagram.com/explore/locations/{{facebookLocationId}}/?__a=1&max_id={{maxId}}'; - const MEDIA_JSON_BY_TAG = 'https://www.instagram.com/graphql/query/?query_id=17882293912014529&tag_name={tag}&first=30&after={max_id}'; + const MEDIA_JSON_BY_TAG = 'https://www.instagram.com/explore/tags/{tag}/?__a=1&max_id={max_id}'; const GENERAL_SEARCH = 'https://www.instagram.com/web/search/topsearch/?query={query}'; const ACCOUNT_JSON_INFO_BY_ID = 'ig_user({userId}){id,username,external_url,full_name,profile_pic_url,biography,followed_by{count},follows{count},media{count},is_private,is_verified}'; const COMMENTS_BEFORE_COMMENT_ID_BY_CODE = 'https://www.instagram.com/graphql/query/?query_id=17852405266163336&shortcode={{shortcode}}&first={{count}}&after={{commentId}}'; @@ -49,10 +49,10 @@ public static function getAccountJsonInfoLinkByAccountId($id) return str_replace('{userId}', urlencode($id), static::ACCOUNT_JSON_INFO_BY_ID); } - public static function getAccountMediasJsonLink($userId, $maxId = '') + public static function getAccountMediasJsonLink($username, $maxId = '') { - $url = str_replace('{user_id}', urlencode($userId), static::ACCOUNT_MEDIAS); - return str_replace('{max_id}', urlencode($maxId), $url); + $url = str_replace('{username}', urlencode($username), static::ACCOUNT_MEDIAS); + return str_replace('{max_id}', urlencode($maxId), $url); } public static function getMediaPageLink($code) diff --git a/classes/InstagramScraper/Instagram.php b/classes/InstagramScraper/Instagram.php index 90388a4..cb6cdb9 100644 --- a/classes/InstagramScraper/Instagram.php +++ b/classes/InstagramScraper/Instagram.php @@ -30,7 +30,6 @@ class Instagram private $sessionUsername; private $sessionPassword; private $userSession; - private $userAgent = null; public $pagingTimeLimitSec = self::PAGING_TIME_LIMIT_SEC; public $pagingDelayMinimumMicrosec = self::PAGING_DELAY_MINIMUM_MICROSEC; @@ -51,7 +50,6 @@ public static function withCredentials($username, $password, $sessionFolder = nu if (is_string($sessionFolder)) { CacheManager::setDefaultConfig([ 'path' => $sessionFolder, - 'ignoreSymfonyNotice' => true, ]); static::$instanceCache = CacheManager::getInstance('files'); } else { @@ -154,35 +152,6 @@ public function searchAccountsByUsername($username) return $accounts; } - /** - * @param $userAgent - * - * @return string - */ - public function setUserAgent($userAgent) - { - return $this->userAgent = $userAgent; - } - - /** - * @param $userAgent - * - * @return null - */ - public function resetUserAgent($userAgent) - { - return $this->userAgent = null; - } - - /** - * - * @return string - */ - public function getUserAgent() - { - return $this->userAgent; - } - /** * @param $session * @@ -197,17 +166,11 @@ private function generateHeaders($session) $cookies .= "$key=$value; "; } $headers = [ - 'cookie' => $cookies, - 'referer' => Endpoints::BASE_URL . '/', + 'cookie' => $cookies, + 'referer' => Endpoints::BASE_URL . '/', 'x-csrftoken' => $session['csrftoken'], ]; } - - if($this->getUserAgent()) - { - $headers['user-agent'] = $this->getUserAgent(); - } - return $headers; } @@ -221,38 +184,43 @@ private function generateHeaders($session) */ public function getMedias($username, $count = 20, $maxId = '') { - $account = $this->getAccount($username); - $index = 0; - $medias = []; - $isMoreAvailable = true; - while ($index < $count && $isMoreAvailable) { - $response = Request::get(Endpoints::getAccountMediasJsonLink($account->getId(), $maxId), $this->generateHeaders($this->userSession)); - 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.'); - } - $nodes = $arr['data']['user']['edge_owner_to_timeline_media']['edges']; - // fix - count takes longer/has more overhead - if (!isset($nodes) || empty($nodes)) { - return []; - } - foreach ($nodes as $mediaArray) { - if ($index === $count) { - return $medias; - } - $medias[] = Media::create($mediaArray['node']); - $index++; - } - if (empty($nodes) || !isset($nodes)) { - return $medias; - } - $maxId = $arr['data']['user']['edge_owner_to_timeline_media']['page_info']['end_cursor']; - $isMoreAvailable = $arr['data']['user']['edge_owner_to_timeline_media']['page_info']['has_next_page']; - } - return $medias; + $index = 0; + $medias = []; + $isMoreAvailable = true; + while ($index < $count && $isMoreAvailable) { + $response = Request::get(Endpoints::getAccountMediasJsonLink($username, $maxId), $this->generateHeaders($this->userSession)); + 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.'); + } + + //print_r($arr); + + $nodes = $arr['graphql']['user']['edge_owner_to_timeline_media']['edges']; + + // fix - count takes longer/has more overhead + if (!isset($nodes) || empty($nodes)) { + return []; + } + foreach ($nodes as $mediaArray) { + if ($index === $count) { + return $medias; + } + $medias[] = Media::create($mediaArray['node']); + $index++; + } + if (empty($nodes) || !isset($nodes)) { + return $medias; + } + $maxId = $nodes[count($nodes) - 1]['node']['id']; + $isMoreAvailable = $arr['graphql']['user']['edge_owner_to_timeline_media']['page_info']['has_next_page']; + $isMoreAvailable = false; + } + return $medias; } /** @@ -320,53 +288,52 @@ public function getMediaByCode($mediaCode) */ public function getPaginateMedias($username, $maxId = '') { - $account = $this->getAccount($username); - $hasNextPage = true; - $medias = []; - - $toReturn = [ - 'medias' => $medias, - 'maxId' => $maxId, - 'hasNextPage' => $hasNextPage, - ]; - - $response = Request::get(Endpoints::getAccountMediasJsonLink($account->getId(), $maxId), - $this->generateHeaders($this->userSession)); - - // use a raw constant in the code is not a good idea!! - //if ($response->code !== 200) { - 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.'); - } - $nodes = $arr['data']['user']['edge_owner_to_timeline_media']['edges']; - - //if (count($arr['items']) === 0) { - // I generally use empty. Im not sure why people would use count really - If the array is large then count takes longer/has more overhead. - // If you simply need to know whether or not the array is empty then use empty. - if (empty($nodes)) { - return $toReturn; - } - - foreach ($nodes as $mediaArray) { - $medias[] = Media::create($mediaArray['node']); - } - - $maxId = $arr['data']['user']['edge_owner_to_timeline_media']['page_info']['end_cursor']; - $isMoreAvailable = $arr['data']['user']['edge_owner_to_timeline_media']['page_info']['has_next_page']; - - $toReturn = [ - 'medias' => $medias, - 'maxId' => $maxId, - 'hasNextPage' => $hasNextPage, - ]; - - return $toReturn; + $hasNextPage = true; + $medias = []; + + $toReturn = [ + 'medias' => $medias, + 'maxId' => $maxId, + 'hasNextPage' => $hasNextPage, + ]; + + $response = Request::get(Endpoints::getAccountMediasJsonLink($username, $maxId), + $this->generateHeaders($this->userSession)); + + // use a raw constant in the code is not a good idea!! + //if ($response->code !== 200) { + 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.'); + } + $nodes = $arr['user']['media']['nodes']; + + //if (count($arr['items']) === 0) { + // I generally use empty. Im not sure why people would use count really - If the array is large then count takes longer/has more overhead. + // If you simply need to know whether or not the array is empty then use empty. + if (empty($nodes)) { + return $toReturn; + } + + foreach ($nodes as $mediaArray) { + $medias[] = Media::create($mediaArray); + } + + $maxId = $arr['user']['media']['page_info']['end_cursor']; + $hasNextPage = $arr['user']['media']['page_info']['has_next_page']; + + $toReturn = [ + 'medias' => $medias, + 'maxId' => $maxId, + 'hasNextPage' => $hasNextPage, + ]; + + return $toReturn; } /** @@ -552,7 +519,7 @@ public function getAccountById($id) Request::curlOpt(CURLOPT_FOLLOWLOCATION, FALSE); $response = Request::get($url, $this->generateHeaders($this->userSession)); Request::curlOpt(CURLOPT_FOLLOWLOCATION, TRUE); - + if ($response->code === 400) { throw new InstagramException('Account with this id does not exist.'); } @@ -590,6 +557,7 @@ public function getAccount($username) } $userArray = json_decode($response->raw_body, true, 512, JSON_BIGINT_AS_STRING); + if (!isset($userArray['graphql']['user'])) { throw new InstagramException('Account with this username does not exist'); } @@ -611,28 +579,43 @@ public function getMediasByTag($tag, $count = 12, $maxId = '', $minTimestamp = n $medias = []; $mediaIds = []; $hasNextPage = true; - while ($index < $count && $hasNextPage) { - - $response = Request::get(Endpoints::getMediasJsonByTagLink($tag, $maxId), - $this->generateHeaders($this->userSession) - ); - + $response = Request::get(Endpoints::getMediasJsonByTagLink($tag, $maxId), + $this->generateHeaders($this->userSession)); if ($response->code !== 200) { throw new InstagramException('Response code is ' . $response->code . '. Body: ' . static::getErrorBody($response->body) . ' Something went wrong. Please report issue.'); } - + $cookies = static::parseCookies($response->headers['Set-Cookie']); $this->userSession['csrftoken'] = $cookies['csrftoken']; $arr = json_decode($response->raw_body, true, 512, JSON_BIGINT_AS_STRING); if (!is_array($arr)) { throw new InstagramException('Response decoding failed. Returned data corrupted or this library outdated. Please report issue'); } - if (empty($arr['data']['hashtag']['edge_hashtag_to_media']['count'])) { + if (empty($arr['graphql']['hashtag']['edge_hashtag_to_media']['count'])) { return []; } - $nodes = $arr['data']['hashtag']['edge_hashtag_to_media']['edges']; - + $nodes = $arr['graphql']['hashtag']['edge_hashtag_to_media']['edges']; + // inWidget fix + $nodesTop = $arr['graphql']['hashtag']['edge_hashtag_to_top_posts']['edges']; + $first = false; + if ($maxId == '') { + $first = true; + } + if($first == true AND !empty($nodesTop)){ + if (count($nodes) < $count AND count($nodesTop) > count($nodes)) { + $tmp = []; + foreach ($nodesTop as $top) { + $tmp[$top['id']] = $top; + foreach ($nodes as $item) { + if(key_exists($item['id'], $tmp)) continue; + $tmp[$item['id']] = $item; + } + } + $nodes = $tmp; + unset($tmp); + } + } foreach ($nodes as $mediaArray) { if ($index === $count) { return $medias; @@ -651,8 +634,8 @@ public function getMediasByTag($tag, $count = 12, $maxId = '', $minTimestamp = n if (empty($nodes)) { return $medias; } - $maxId = $arr['data']['hashtag']['edge_hashtag_to_media']['page_info']['end_cursor']; - $hasNextPage = $arr['data']['hashtag']['edge_hashtag_to_media']['page_info']['has_next_page']; + $maxId = $arr['graphql']['hashtag']['edge_hashtag_to_media']['page_info']['end_cursor']; + $hasNextPage = $arr['graphql']['hashtag']['edge_hashtag_to_media']['page_info']['has_next_page']; } return $medias; } @@ -740,9 +723,8 @@ public function getCurrentTopMediasByTagName($tagName) $this->userSession['csrftoken'] = $cookies['csrftoken']; $jsonResponse = json_decode($response->raw_body, true, 512, JSON_BIGINT_AS_STRING); $medias = []; - $nodes = (array) @$jsonResponse['graphql']['hashtag']['edge_hashtag_to_media']['edges']; - foreach ($nodes as $mediaArray) { - $medias[] = Media::create($mediaArray['node']); + foreach ($jsonResponse['tag']['top_posts']['nodes'] as $mediaArray) { + $medias[] = Media::create($mediaArray); } return $medias; } diff --git a/classes/InstagramScraper/Model/Account.php b/classes/InstagramScraper/Model/Account.php index 01f76e0..e479baf 100644 --- a/classes/InstagramScraper/Model/Account.php +++ b/classes/InstagramScraper/Model/Account.php @@ -32,12 +32,6 @@ class Account extends AbstractModel */ protected $profilePicUrl = ''; - /** - * Profile picture url HD - * @var string - */ - protected $profilePicUrlHd = ''; - /** * Information filled by user * @var string @@ -129,20 +123,6 @@ public function getProfilePicUrl() return $this->profilePicUrl; } - /** - * @return string - */ - public function getProfilePicUrlHd() - { - $toReturn = $this->profilePicUrl; - - if ($this->profilePicUrlHd !== '') { - $toReturn = $this->profilePicUrlHd; - } - - return $toReturn; - } - /** * @return string */ @@ -219,9 +199,6 @@ protected function initPropertiesCustom($value, $prop, $array) case 'profile_pic_url': $this->profilePicUrl = $value; break; - case 'profile_pic_url_hd': - $this->profilePicUrlHd = $value; - break; case 'biography': $this->biography = $value; break; @@ -245,4 +222,4 @@ protected function initPropertiesCustom($value, $prop, $array) break; } } -} +} \ No newline at end of file diff --git a/classes/InstagramScraper/Model/Media.php b/classes/InstagramScraper/Model/Media.php index d477b32..8e175ff 100644 --- a/classes/InstagramScraper/Model/Media.php +++ b/classes/InstagramScraper/Model/Media.php @@ -10,607 +10,607 @@ */ class Media extends AbstractModel { - const TYPE_IMAGE = 'image'; - const TYPE_VIDEO = 'video'; - const TYPE_SIDECAR = 'sidecar'; - const TYPE_CAROUSEL = 'carousel'; - - /** - * @var string - */ - protected $id = ''; - - /** - * @var string - */ - protected $shortCode = ''; - - /** - * @var int - */ - protected $createdTime = 0; - - /** - * @var string - */ - protected $type = ''; - - /** - * @var string - */ - protected $link = ''; - - /** - * @var string - */ - protected $imageLowResolutionUrl = ''; - - /** - * @var string - */ - protected $imageThumbnailUrl = ''; - - /** - * @var string - */ - protected $imageStandardResolutionUrl = ''; - - /** - * @var string - */ - protected $imageHighResolutionUrl = ''; - - /** - * @var array - */ - protected $squareThumbnailsUrl = []; - - /** - * @var array - */ - protected $carouselMedia = []; - - /** - * @var string - */ - protected $caption = ''; - - /** - * @var bool - */ - protected $isCaptionEdited = false; - - /** - * @var bool - */ - protected $isAd = false; - - /** - * @var string - */ - protected $videoLowResolutionUrl = ''; - - /** - * @var string - */ - protected $videoStandardResolutionUrl = ''; - - /** - * @var string - */ - protected $videoLowBandwidthUrl = ''; - - /** - * @var int - */ - protected $videoViews = 0; - - /** - * @var Account - */ - protected $owner; - - /** - * @var int - */ - protected $ownerId = 0; - - /** - * @var int - */ - protected $likesCount = 0; - - /** - * @var - */ - protected $locationId; - - /** - * @var string - */ - protected $locationName = ''; - - /** - * @var string - */ - protected $commentsCount = 0; - - /** - * @var Media[]|array - */ - protected $sidecarMedias = []; - - /** - * @param string $code - * - * @return int - */ - public static function getIdFromCode($code) - { - $alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_'; - $id = 0; - for ($i = 0; $i < strlen($code); $i++) { - $c = $code[$i]; - $id = $id * 64 + strpos($alphabet, $c); - } - return $id; - } - - /** - * @param string $id - * - * @return mixed - */ - public static function getLinkFromId($id) - { - $code = Media::getCodeFromId($id); - return Endpoints::getMediaPageLink($code); - } - - /** - * @param string $id - * - * @return string - */ - public static function getCodeFromId($id) - { - $parts = explode('_', $id); - $id = $parts[0]; - $alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_'; - $code = ''; - while ($id > 0) { - $remainder = $id % 64; - $id = ($id - $remainder) / 64; - $code = $alphabet{$remainder} . $code; - }; - return $code; - } - - /** - * @return mixed - */ - public function getId() - { - return $this->id; - } - - /** - * @return string - */ - public function getShortCode() - { - return $this->shortCode; - } - - /** - * @return int - */ - public function getCreatedTime() - { - return $this->createdTime; - } - - /** - * @return string - */ - public function getType() - { - return $this->type; - } - - /** - * @return string - */ - public function getLink() - { - return $this->link; - } - - /** - * @return string - */ - public function getImageLowResolutionUrl() - { - return $this->imageLowResolutionUrl; - } - - /** - * @return string - */ - public function getImageThumbnailUrl() - { - return $this->imageThumbnailUrl; - } - - /** - * @return string - */ - public function getImageStandardResolutionUrl() - { - return $this->imageStandardResolutionUrl; - } - - /** - * @return string - */ - public function getImageHighResolutionUrl() - { - return $this->imageHighResolutionUrl; - } - - - /** - * @return array - */ - public function getSquareThumbnailsUrl() { - return $this->squareThumbnailsUrl; - } - - - /** - * @return array - */ - public function getCarouselMedia() - { - return $this->carouselMedia; - } - - /** - * @return string - */ - public function getCaption() - { - return $this->caption; - } - - /** - * @return bool - */ - public function isCaptionEdited() - { - return $this->isCaptionEdited; - } - - /** - * @return bool - */ - public function isAd() - { - return $this->isAd; - } - - /** - * @return string - */ - public function getVideoLowResolutionUrl() - { - return $this->videoLowResolutionUrl; - } - - /** - * @return string - */ - public function getVideoStandardResolutionUrl() - { - return $this->videoStandardResolutionUrl; - } - - /** - * @return string - */ - public function getVideoLowBandwidthUrl() - { - return $this->videoLowBandwidthUrl; - } - - /** - * @return int - */ - public function getVideoViews() - { - return $this->videoViews; - } - - /** - * @return int - */ - public function getOwnerId() - { - return $this->ownerId; - } - - /** - * @return int - */ - public function getLikesCount() - { - return $this->likesCount; - } - - /** - * @return mixed - */ - public function getLocationId() - { - return $this->locationId; - } - - /** - * @return string - */ - public function getLocationName() - { - return $this->locationName; - } - - /** - * @return string - */ - public function getCommentsCount() - { - return $this->commentsCount; - } - - /** - * @return Media[]|array - */ - public function getSidecarMedias() - { - return $this->sidecarMedias; - } - - /** - * @param $value - * @param $prop - */ - protected function initPropertiesCustom($value, $prop, $arr) - { - switch ($prop) { - case 'id': - $this->id = $value; - break; - case 'type': - $this->type = $value; - break; - case 'created_time': - $this->createdTime = (int)$value; - break; - case 'code': - $this->shortCode = $value; - $this->link = Endpoints::getMediaPageLink($this->shortCode); - break; - case 'link': - $this->link = $value; - break; - case 'comments': - $this->commentsCount = $arr[$prop]['count']; - break; - case 'likes': - $this->likesCount = $arr[$prop]['count']; - break; - case 'thumbnail_resources': - foreach( $value as $thumbnail ) { - $thumbnailsUrl[] = $thumbnail['src']; - switch ($thumbnail['config_width']) { - case 150: - $this->imageThumbnailUrl = $thumbnail['src']; - break; - case 320: - $this->imageLowResolutionUrl = $thumbnail['src']; - break; - case 640: - $this->imageStandardResolutionUrl = $thumbnail['src']; - break; - default:; - } - } - $this->squareThumbnailsUrl = $thumbnailsUrl; - break; - case 'thumbnail_src': - if(empty($this->imageThumbnailUrl)) { - $this->imageThumbnailUrl = $value; - $this->imageLowResolutionUrl = $value; - $this->imageStandardResolutionUrl = $value; - } - break; - case 'display_url': - $this->imageHighResolutionUrl = $value; - break; - case 'display_src': - $this->imageHighResolutionUrl = $value; - if (!isset($this->type)) { - $this->type = static::TYPE_IMAGE; - } - break; - case 'carousel_media': - $this->type = self::TYPE_CAROUSEL; - $this->carouselMedia = []; - foreach ($arr["carousel_media"] as $carouselArray) { - self::setCarouselMedia($arr, $carouselArray, $this); - } - break; - case 'caption': - $this->caption = $arr[$prop]; - break; - case 'video_views': - $this->videoViews = $value; - $this->type = static::TYPE_VIDEO; - break; - case 'videos': - $this->videoLowResolutionUrl = $arr[$prop]['low_resolution']['url']; - $this->videoStandardResolutionUrl = $arr[$prop]['standard_resolution']['url']; - $this->videoLowBandwidthUrl = $arr[$prop]['low_bandwidth']['url']; - break; - case 'video_resources': - foreach ($value as $video) { - if ($video['profile'] == 'MAIN') { - $this->videoStandardResolutionUrl = $video['src']; - } elseif ($video['profile'] == 'BASELINE') { - $this->videoLowResolutionUrl = $video['src']; - $this->videoLowBandwidthUrl = $video['src']; - } - } - break; - case 'location': - $this->locationId = $arr[$prop]['id']; - $this->locationName = $arr[$prop]['name']; - break; - case 'user': - $this->owner = Account::create($arr[$prop]); - break; - case 'is_video': - if ((bool)$value) { - $this->type = static::TYPE_VIDEO; - } - break; - case 'video_url': - $this->videoStandardResolutionUrl = $value; - break; - case 'video_view_count': - $this->videoViews = $value; - break; - case 'caption_is_edited': - $this->isCaptionEdited = $value; - break; - case 'is_ad': - $this->isAd = $value; - break; - case 'taken_at_timestamp': - $this->createdTime = $value; - break; - case 'shortcode': - $this->shortCode = $value; - $this->link = Endpoints::getMediaPageLink($this->shortCode); - break; - case 'edge_media_to_comment': - $this->commentsCount = $arr[$prop]['count']; - break; - case 'edge_media_preview_like': - $this->likesCount = $arr[$prop]['count']; - break; - case 'edge_liked_by': - $this->likesCount = $arr[$prop]['count']; - break; - case 'edge_media_to_caption': - if (is_array($arr[$prop]['edges']) && !empty($arr[$prop]['edges'])) { - $first_caption = $arr[$prop]['edges'][0]; - if (is_array($first_caption) && isset($first_caption['node'])) { - if (is_array($first_caption['node']) && isset($first_caption['node']['text'])) { - $this->caption = $arr[$prop]['edges'][0]['node']['text']; - } - } - } - break; - case 'edge_sidecar_to_children': - if (!is_array($arr[$prop]['edges'])) { - break; - } - foreach ($arr[$prop]['edges'] as $edge) { - if (!isset($edge['node'])) { - continue; - } - - $this->sidecarMedias[] = static::create($edge['node']); - } - break; - case 'owner': - $this->owner = Account::create($arr[$prop]); - break; - case 'date': - $this->createdTime = (int)$value; - break; - case '__typename': - if ($value == 'GraphImage') { - $this->type = static::TYPE_IMAGE; - } else if ($value == 'GraphVideo') { - $this->type = static::TYPE_VIDEO; - } else if ($value == 'GraphSidecar') { - $this->type = static::TYPE_SIDECAR; - } - break; - } - if (!$this->ownerId && !is_null($this->owner)) { - $this->ownerId = $this->getOwner()->getId(); - } - } - - /** - * @param string $imageUrl - * - * @return array - */ - private static function getImageUrls($imageUrl) - { - $parts = explode('/', parse_url($imageUrl)['path']); - $imageName = $parts[sizeof($parts) - 1]; - $urls = [ - 'thumbnail' => Endpoints::INSTAGRAM_CDN_URL . 't/s150x150/' . $imageName, - 'low' => Endpoints::INSTAGRAM_CDN_URL . 't/s320x320/' . $imageName, - 'standard' => Endpoints::INSTAGRAM_CDN_URL . 't/s640x640/' . $imageName, - 'high' => Endpoints::INSTAGRAM_CDN_URL . 't/' . $imageName, - ]; - return $urls; - } - - /** - * @param $mediaArray - * @param $carouselArray - * @param $instance - * - * @return mixed - */ - private static function setCarouselMedia($mediaArray, $carouselArray, $instance) - { - $carouselMedia = new CarouselMedia(); - $carouselMedia->setType($carouselArray['type']); - - if (isset($carouselArray['images'])) { - $carouselImages = self::getImageUrls($carouselArray['images']['standard_resolution']['url']); - $carouselMedia->setImageLowResolutionUrl($carouselImages['low']); - $carouselMedia->setImageThumbnailUrl($carouselImages['thumbnail']); - $carouselMedia->setImageStandardResolutionUrl($carouselImages['standard']); - $carouselMedia->setImageHighResolutionUrl($carouselImages['high']); - } - - if ($carouselMedia->getType() === self::TYPE_VIDEO) { - if (isset($mediaArray['video_views'])) { - $carouselMedia->setVideoViews($carouselArray['video_views']); - } - if (isset($carouselArray['videos'])) { - $carouselMedia->setVideoLowResolutionUrl($carouselArray['videos']['low_resolution']['url']); - $carouselMedia->setVideoStandardResolutionUrl($carouselArray['videos']['standard_resolution']['url']); - $carouselMedia->setVideoLowBandwidthUrl($carouselArray['videos']['low_bandwidth']['url']); - } - } - array_push($instance->carouselMedia, $carouselMedia); - return $mediaArray; - } - - /** - * @return Account - */ - public function getOwner() - { - return $this->owner; - } + const TYPE_IMAGE = 'image'; + const TYPE_VIDEO = 'video'; + const TYPE_SIDECAR = 'sidecar'; + const TYPE_CAROUSEL = 'carousel'; + + /** + * @var string + */ + protected $id = ''; + + /** + * @var string + */ + protected $shortCode = ''; + + /** + * @var int + */ + protected $createdTime = 0; + + /** + * @var string + */ + protected $type = ''; + + /** + * @var string + */ + protected $link = ''; + + /** + * @var string + */ + protected $imageLowResolutionUrl = ''; + + /** + * @var string + */ + protected $imageThumbnailUrl = ''; + + /** + * @var string + */ + protected $imageStandardResolutionUrl = ''; + + /** + * @var string + */ + protected $imageHighResolutionUrl = ''; + + /** + * @var array + */ + protected $squareThumbnailsUrl = []; + + /** + * @var array + */ + protected $carouselMedia = []; + + /** + * @var string + */ + protected $caption = ''; + + /** + * @var bool + */ + protected $isCaptionEdited = false; + + /** + * @var bool + */ + protected $isAd = false; + + /** + * @var string + */ + protected $videoLowResolutionUrl = ''; + + /** + * @var string + */ + protected $videoStandardResolutionUrl = ''; + + /** + * @var string + */ + protected $videoLowBandwidthUrl = ''; + + /** + * @var int + */ + protected $videoViews = 0; + + /** + * @var Account + */ + protected $owner; + + /** + * @var int + */ + protected $ownerId = 0; + + /** + * @var int + */ + protected $likesCount = 0; + + /** + * @var + */ + protected $locationId; + + /** + * @var string + */ + protected $locationName = ''; + + /** + * @var string + */ + protected $commentsCount = 0; + + /** + * @var Media[]|array + */ + protected $sidecarMedias = []; + + /** + * @param string $code + * + * @return int + */ + public static function getIdFromCode($code) + { + $alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_'; + $id = 0; + for ($i = 0; $i < strlen($code); $i++) { + $c = $code[$i]; + $id = $id * 64 + strpos($alphabet, $c); + } + return $id; + } + + /** + * @param string $id + * + * @return mixed + */ + public static function getLinkFromId($id) + { + $code = Media::getCodeFromId($id); + return Endpoints::getMediaPageLink($code); + } + + /** + * @param string $id + * + * @return string + */ + public static function getCodeFromId($id) + { + $parts = explode('_', $id); + $id = $parts[0]; + $alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_'; + $code = ''; + while ($id > 0) { + $remainder = $id % 64; + $id = ($id - $remainder) / 64; + $code = $alphabet{$remainder} . $code; + }; + return $code; + } + + /** + * @return mixed + */ + public function getId() + { + return $this->id; + } + + /** + * @return string + */ + public function getShortCode() + { + return $this->shortCode; + } + + /** + * @return int + */ + public function getCreatedTime() + { + return $this->createdTime; + } + + /** + * @return string + */ + public function getType() + { + return $this->type; + } + + /** + * @return string + */ + public function getLink() + { + return $this->link; + } + + /** + * @return string + */ + public function getImageLowResolutionUrl() + { + return $this->imageLowResolutionUrl; + } + + /** + * @return string + */ + public function getImageThumbnailUrl() + { + return $this->imageThumbnailUrl; + } + + /** + * @return string + */ + public function getImageStandardResolutionUrl() + { + return $this->imageStandardResolutionUrl; + } + + /** + * @return string + */ + public function getImageHighResolutionUrl() + { + return $this->imageHighResolutionUrl; + } + + + /** + * @return array + */ + public function getSquareThumbnailsUrl() { + return $this->squareThumbnailsUrl; + } + + + /** + * @return array + */ + public function getCarouselMedia() + { + return $this->carouselMedia; + } + + /** + * @return string + */ + public function getCaption() + { + return $this->caption; + } + + /** + * @return bool + */ + public function isCaptionEdited() + { + return $this->isCaptionEdited; + } + + /** + * @return bool + */ + public function isAd() + { + return $this->isAd; + } + + /** + * @return string + */ + public function getVideoLowResolutionUrl() + { + return $this->videoLowResolutionUrl; + } + + /** + * @return string + */ + public function getVideoStandardResolutionUrl() + { + return $this->videoStandardResolutionUrl; + } + + /** + * @return string + */ + public function getVideoLowBandwidthUrl() + { + return $this->videoLowBandwidthUrl; + } + + /** + * @return int + */ + public function getVideoViews() + { + return $this->videoViews; + } + + /** + * @return int + */ + public function getOwnerId() + { + return $this->ownerId; + } + + /** + * @return int + */ + public function getLikesCount() + { + return $this->likesCount; + } + + /** + * @return mixed + */ + public function getLocationId() + { + return $this->locationId; + } + + /** + * @return string + */ + public function getLocationName() + { + return $this->locationName; + } + + /** + * @return string + */ + public function getCommentsCount() + { + return $this->commentsCount; + } + + /** + * @return Media[]|array + */ + public function getSidecarMedias() + { + return $this->sidecarMedias; + } + + /** + * @param $value + * @param $prop + */ + protected function initPropertiesCustom($value, $prop, $arr) + { + switch ($prop) { + case 'id': + $this->id = $value; + break; + case 'type': + $this->type = $value; + break; + case 'created_time': + $this->createdTime = (int)$value; + break; + case 'code': + $this->shortCode = $value; + $this->link = Endpoints::getMediaPageLink($this->shortCode); + break; + case 'link': + $this->link = $value; + break; + case 'comments': + $this->commentsCount = $arr[$prop]['count']; + break; + case 'likes': + $this->likesCount = $arr[$prop]['count']; + break; + case 'thumbnail_resources': + foreach( $value as $thumbnail ) { + $thumbnailsUrl[] = $thumbnail['src']; + switch ($thumbnail['config_width']) { + case 150: + $this->imageThumbnailUrl = $thumbnail['src']; + break; + case 320: + $this->imageLowResolutionUrl = $thumbnail['src']; + break; + case 640: + $this->imageStandardResolutionUrl = $thumbnail['src']; + break; + default:; + } + } + $this->squareThumbnailsUrl = $thumbnailsUrl; + break; + case 'thumbnail_src': + if(empty($this->imageThumbnailUrl)) { + $this->imageThumbnailUrl = $value; + $this->imageLowResolutionUrl = $value; + $this->imageStandardResolutionUrl = $value; + } + break; + case 'display_url': + $this->imageHighResolutionUrl = $value; + break; + case 'display_src': + $this->imageHighResolutionUrl = $value; + if (!isset($this->type)) { + $this->type = static::TYPE_IMAGE; + } + break; + case 'carousel_media': + $this->type = self::TYPE_CAROUSEL; + $this->carouselMedia = []; + foreach ($arr["carousel_media"] as $carouselArray) { + self::setCarouselMedia($arr, $carouselArray, $this); + } + break; + case 'caption': + $this->caption = $arr[$prop]; + break; + case 'video_views': + $this->videoViews = $value; + $this->type = static::TYPE_VIDEO; + break; + case 'videos': + $this->videoLowResolutionUrl = $arr[$prop]['low_resolution']['url']; + $this->videoStandardResolutionUrl = $arr[$prop]['standard_resolution']['url']; + $this->videoLowBandwidthUrl = $arr[$prop]['low_bandwidth']['url']; + break; + case 'video_resources': + foreach ($value as $video) { + if ($video['profile'] == 'MAIN') { + $this->videoStandardResolutionUrl = $video['src']; + } elseif ($video['profile'] == 'BASELINE') { + $this->videoLowResolutionUrl = $video['src']; + $this->videoLowBandwidthUrl = $video['src']; + } + } + break; + case 'location': + $this->locationId = $arr[$prop]['id']; + $this->locationName = $arr[$prop]['name']; + break; + case 'user': + $this->owner = Account::create($arr[$prop]); + break; + case 'is_video': + if ((bool)$value) { + $this->type = static::TYPE_VIDEO; + } + break; + case 'video_url': + $this->videoStandardResolutionUrl = $value; + break; + case 'video_view_count': + $this->videoViews = $value; + break; + case 'caption_is_edited': + $this->isCaptionEdited = $value; + break; + case 'is_ad': + $this->isAd = $value; + break; + case 'taken_at_timestamp': + $this->createdTime = $value; + break; + case 'shortcode': + $this->shortCode = $value; + $this->link = Endpoints::getMediaPageLink($this->shortCode); + break; + case 'edge_media_to_comment': + $this->commentsCount = $arr[$prop]['count']; + break; + case 'edge_media_preview_like': + $this->likesCount = $arr[$prop]['count']; + break; + case 'edge_liked_by': + $this->likesCount = $arr[$prop]['count']; + break; + case 'edge_media_to_caption': + if (is_array($arr[$prop]['edges']) && !empty($arr[$prop]['edges'])) { + $first_caption = $arr[$prop]['edges'][0]; + if (is_array($first_caption) && isset($first_caption['node'])) { + if (is_array($first_caption['node']) && isset($first_caption['node']['text'])) { + $this->caption = $arr[$prop]['edges'][0]['node']['text']; + } + } + } + break; + case 'edge_sidecar_to_children': + if (!is_array($arr[$prop]['edges'])) { + break; + } + foreach ($arr[$prop]['edges'] as $edge) { + if (!isset($edge['node'])) { + continue; + } + + $this->sidecarMedias[] = static::create($edge['node']); + } + break; + case 'owner': + $this->owner = Account::create($arr[$prop]); + break; + case 'date': + $this->createdTime = (int)$value; + break; + case '__typename': + if ($value == 'GraphImage') { + $this->type = static::TYPE_IMAGE; + } else if ($value == 'GraphVideo') { + $this->type = static::TYPE_VIDEO; + } else if ($value == 'GraphSidecar') { + $this->type = static::TYPE_SIDECAR; + } + break; + } + if (!$this->ownerId && !is_null($this->owner)) { + $this->ownerId = $this->getOwner()->getId(); + } + } + + /** + * @param string $imageUrl + * + * @return array + */ + private static function getImageUrls($imageUrl) + { + $parts = explode('/', parse_url($imageUrl)['path']); + $imageName = $parts[sizeof($parts) - 1]; + $urls = [ + 'thumbnail' => Endpoints::INSTAGRAM_CDN_URL . 't/s150x150/' . $imageName, + 'low' => Endpoints::INSTAGRAM_CDN_URL . 't/s320x320/' . $imageName, + 'standard' => Endpoints::INSTAGRAM_CDN_URL . 't/s640x640/' . $imageName, + 'high' => Endpoints::INSTAGRAM_CDN_URL . 't/' . $imageName, + ]; + return $urls; + } + + /** + * @param $mediaArray + * @param $carouselArray + * @param $instance + * + * @return mixed + */ + private static function setCarouselMedia($mediaArray, $carouselArray, $instance) + { + $carouselMedia = new CarouselMedia(); + $carouselMedia->setType($carouselArray['type']); + + if (isset($carouselArray['images'])) { + $carouselImages = self::getImageUrls($carouselArray['images']['standard_resolution']['url']); + $carouselMedia->setImageLowResolutionUrl($carouselImages['low']); + $carouselMedia->setImageThumbnailUrl($carouselImages['thumbnail']); + $carouselMedia->setImageStandardResolutionUrl($carouselImages['standard']); + $carouselMedia->setImageHighResolutionUrl($carouselImages['high']); + } + + if ($carouselMedia->getType() === self::TYPE_VIDEO) { + if (isset($mediaArray['video_views'])) { + $carouselMedia->setVideoViews($carouselArray['video_views']); + } + if (isset($carouselArray['videos'])) { + $carouselMedia->setVideoLowResolutionUrl($carouselArray['videos']['low_resolution']['url']); + $carouselMedia->setVideoStandardResolutionUrl($carouselArray['videos']['standard_resolution']['url']); + $carouselMedia->setVideoLowBandwidthUrl($carouselArray['videos']['low_bandwidth']['url']); + } + } + array_push($instance->carouselMedia, $carouselMedia); + return $mediaArray; + } + + /** + * @return Account + */ + public function getOwner() + { + return $this->owner; + } } diff --git a/index.php b/index.php index c46eb9b..0022a4b 100644 --- a/index.php +++ b/index.php @@ -11,7 +11,7 @@ * @link http://inwidget.ru * @copyright 2014-2018 Alexandr Kazarmshchikov * @author Alexandr Kazarmshchikov - * @version 1.2.4 + * @version 1.2.5 * @package inWidget * */ @@ -44,7 +44,6 @@ /* ----------------------------------------------------------- Custom initialization ------------------------------------------------------------*/ - /* try { diff --git a/langs/en.php b/langs/en.php index 83a8957..c508b01 100644 --- a/langs/en.php +++ b/langs/en.php @@ -10,7 +10,6 @@ * @link http://inwidget.ru * @copyright 2014-2018 Alexandr Kazarmshchikov * @author Alexandr Kazarmshchikov - * @version 1.2.4 * @package inWidget * */ diff --git a/langs/ru.php b/langs/ru.php index 513a73d..1063afd 100644 --- a/langs/ru.php +++ b/langs/ru.php @@ -10,7 +10,6 @@ * @link http://inwidget.ru * @copyright 2014-2018 Alexandr Kazarmshchikov * @author Alexandr Kazarmshchikov - * @version 1.2.4 * @package inWidget * */ diff --git a/langs/ua.php b/langs/ua.php index b3c7224..f3a9151 100644 --- a/langs/ua.php +++ b/langs/ua.php @@ -10,7 +10,6 @@ * @link http://inwidget.ru * @copyright 2014-2018 Alexandr Kazarmshchikov * @author Alexandr Kazarmshchikov - * @version 1.2.4 * @package inWidget * */ diff --git a/readme.txt b/readme.txt index e7c6098..cd37434 100644 --- a/readme.txt +++ b/readme.txt @@ -8,7 +8,7 @@ * * @link http://inwidget.ru * @author Alexandr Kazarmshchikov - * @version 1.2.4 + * @version 1.2.5 * @package inWidget * */ @@ -238,6 +238,14 @@ catch (\Exception $e) { // История версий: // ---------------------------------------- +inWidget-1.2.5 +Дата: 07 апреля 2018 г. + +* Откат изменений к версии 1.2.1 в связи с тем, что узел (/graphql/query/?query_id=) перестал работать +* Добавление изменений из версии 1.2.3 +* В данной версии нельзя извлечь более 12 фото из аккаунта при использовании недокументированного API (при поиске по тегам можно). Решение в процессе поиска. +* Начиная с 04 апреля 2018 г. официальное Endpoint API более не актуально. Указание ACCESS_TOKEN в настройках не имеет смысла. + inWidget-1.2.4 Дата: 27 марта 2018 г. diff --git a/template.php b/template.php index 7b5d021..546d1aa 100644 --- a/template.php +++ b/template.php @@ -10,7 +10,6 @@ * @link http://inwidget.ru * @copyright 2014-2018 Alexandr Kazarmshchikov * @author Alexandr Kazarmshchikov - * @version 1.2.4 * @package inWidget * */