diff --git a/bridges/InstagramBridge.php b/bridges/InstagramBridge.php index fe712b86..679c4c0e 100644 --- a/bridges/InstagramBridge.php +++ b/bridges/InstagramBridge.php @@ -32,14 +32,14 @@ class InstagramBridge extends BridgeAbstract { 'required' => false, 'values' => array( 'All' => 'all', - 'Story' => 'story', 'Video' => 'video', 'Picture' => 'picture', + 'Multiple' => 'multiple', ), 'defaultValue' => 'all' ), 'direct_links' => array( - 'name' => 'Use direct image links', + 'name' => 'Use direct media links', 'type' => 'checkbox', ) ) @@ -48,7 +48,7 @@ class InstagramBridge extends BridgeAbstract { const USER_QUERY_HASH = '58b6785bea111c67129decbe6a448951'; const TAG_QUERY_HASH = '174a5243287c5f3a7de741089750ab3b'; - const STORY_QUERY_HASH = '865589822932d1b43dfe312121dd353a'; + const SHORTCODE_QUERY_HASH = '865589822932d1b43dfe312121dd353a'; protected function getInstagramUserId($username) { @@ -79,11 +79,6 @@ class InstagramBridge extends BridgeAbstract { } public function collectData(){ - - if(is_null($this->getInput('u')) && $this->getInput('media_type') == 'story') { - returnClientError('Stories are not supported for hashtags nor locations!'); - } - $directLink = !is_null($this->getInput('direct_links')) && $this->getInput('direct_links'); $data = $this->getInstagramJSON($this->getURI()); @@ -99,22 +94,18 @@ class InstagramBridge extends BridgeAbstract { foreach($userMedia as $media) { $media = $media->node; - if(!is_null($this->getInput('u'))) { - switch($this->getInput('media_type')) { - case 'all': break; - case 'video': - if($media->__typename != 'GraphVideo') continue 2; - break; - case 'picture': - if($media->__typename != 'GraphImage') continue 2; - break; - case 'story': - if($media->__typename != 'GraphSidecar') continue 2; - break; - default: break; - } - } else { - if($this->getInput('media_type') == 'video' && !$media->is_video) continue; + switch($this->getInput('media_type')) { + case 'all': break; + case 'video': + if($media->__typename != 'GraphVideo' || !$media->is_video) continue 2; + break; + case 'picture': + if($media->__typename != 'GraphImage') continue 2; + break; + case 'multiple': + if($media->__typename != 'GraphSidecar') continue 2; + break; + default: break; } $item = array(); @@ -124,73 +115,105 @@ class InstagramBridge extends BridgeAbstract { $item['author'] = $media->owner->username; } - if (isset($media->edge_media_to_caption->edges[0]->node->text)) { - $textContent = $media->edge_media_to_caption->edges[0]->node->text; - } else { - $textContent = '(no text)'; - } + $textContent = $this->getTextContent($media); - $item['title'] = ($media->is_video ? '▶ ' : '') . trim($textContent); + $item['title'] = ($media->is_video ? '▶ ' : '') . $textContent; $titleLinePos = strpos(wordwrap($item['title'], 120), "\n"); if ($titleLinePos != false) { $item['title'] = substr($item['title'], 0, $titleLinePos) . '...'; } - if(!is_null($this->getInput('u')) && $media->__typename == 'GraphSidecar') { - - $data = $this->getInstagramStory($item['uri']); - $item['content'] = $data[0]; - $item['enclosures'] = $data[1]; - } else { - if($directLink) { - $mediaURI = $media->display_url; - } else { - $mediaURI = self::URI . 'p/' . $media->shortcode . '/media?size=l'; - } - $item['content'] = ''; - $item['content'] .= '' . $item['title'] . ''; - $item['content'] .= '

' . nl2br(htmlentities($textContent)); - $item['enclosures'] = array($mediaURI); + switch($media->__typename) { + case 'GraphSidecar': + $data = $this->getInstagramSidecarData($item['uri'], $item['title']); + $item['content'] = $data[0]; + $item['enclosures'] = $data[1]; + break; + case 'GraphImage': + if($directLink) { + $mediaURI = $media->display_url; + } else { + $mediaURI = self::URI . 'p/' . $media->shortcode . '/media?size=l'; + } + $item['content'] = ''; + $item['content'] .= '' . $item['title'] . ''; + $item['content'] .= '

' . nl2br(htmlentities($textContent)); + $item['enclosures'] = array($mediaURI); + break; + case 'GraphVideo': + $data = $this->getInstagramVideoData($item['uri']); + $item['content'] = $data[0]; + if($directLink) { + $item['enclosures'] = $data[1]; + } else { + $item['enclosures'] = array(self::URI . 'p/' . $media->shortcode . '/media?size=l'); + } + break; + default: break; } - $item['timestamp'] = $media->taken_at_timestamp; $this->items[] = $item; } } - protected function getInstagramStory($uri) { + // returns Sidecar(a post which has multiple media)'s contents and enclosures + protected function getInstagramSidecarData($uri, $postTitle) { + $mediaInfo = $this->getSinglePostData($uri); + $textContent = $this->getTextContent($mediaInfo); + + $enclosures = array(); + $content = ''; + foreach($mediaInfo->edge_sidecar_to_children->edges as $singleMedia) { + $singleMedia = $singleMedia->node; + if($singleMedia->is_video) { + if(in_array($singleMedia->video_url, $enclosures)) continue; // check if not added yet + $content .= '
'; + array_push($enclosures, $singleMedia->video_url); + } else { + if(in_array($singleMedia->display_url, $enclosures)) continue; // check if not added yet + $content .= ''; + $content .= '' . $postTitle . ''; + $content .= '
'; + array_push($enclosures, $singleMedia->display_url); + } + } + $content .= '
' . nl2br(htmlentities($textContent)); + + return array($content, $enclosures); + } + + // returns Video post's contents and enclosures + protected function getInstagramVideoData($uri) { + $mediaInfo = $this->getSinglePostData($uri); + + $textContent = $this->getTextContent($mediaInfo); + $content = '
'; + $content .= '
' . nl2br(htmlentities($textContent)); + + return array($content, array($mediaInfo->video_url)); + } + + protected function getTextContent($media) { + $textContent = '(no text)'; + //Process the first element, that isn't in the node graph + if (count($media->edge_media_to_caption->edges) > 0) { + $textContent = trim($media->edge_media_to_caption->edges[0]->node->text); + } + return $textContent; + } + + protected function getSinglePostData($uri) { $shortcode = explode('/', $uri)[4]; $data = getContents(self::URI . 'graphql/query/?query_hash=' . - self::STORY_QUERY_HASH . - '&variables={"shortcode"%3A"' . + self::SHORTCODE_QUERY_HASH . + '&variables={"shortcode"%3A"' . $shortcode . '"}'); - $mediaInfo = json_decode($data)->data->shortcode_media; - - //Process the first element, that isn't in the node graph - if (count($mediaInfo->edge_media_to_caption->edges) > 0) { - $caption = $mediaInfo->edge_media_to_caption->edges[0]->node->text; - } else { - $caption = ''; - } - - $enclosures = array($mediaInfo->display_url); - $content = '' . $caption . ''; - - foreach($mediaInfo->edge_sidecar_to_children->edges as $media) { - $display_url = $media->node->display_url; - if(!in_array($display_url, $enclosures)) { // add only if not added yet - $content .= '' . $caption . ''; - $enclosures[] = $display_url; - } - } - - return array($content, $enclosures); - + return json_decode($data)->data->shortcode_media; } protected function getInstagramJSON($uri) {