Skip to content

Commit

Permalink
adopt Instagram changes
Browse files Browse the repository at this point in the history
  • Loading branch information
kringkaste committed Jun 3, 2022
1 parent da2c9b0 commit b82407f
Show file tree
Hide file tree
Showing 5 changed files with 117 additions and 23 deletions.
47 changes: 43 additions & 4 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
# Instagram Feed Changelog
# Release Notes for Instagram Feed Plugin

## 2.0.1 - 2022-06-03 [CRITICAL]

> {note} Instagram has changed the data structure on 06/01/2022. Without this update, the plugin will no longer work.
### Changed

- Adaptation to the changes in the data structure of Instagram on 06/01/2022.

## 2.0.0 - 2021-04-29

Expand Down Expand Up @@ -26,93 +34,116 @@
## 1.1.7 - 2021-07-19

### Changed

- Add PHP 8 to composer version constraint.

## 1.1.6 - 2021-07-16

### Changed

- Removed file_get_contents() and always use Guzzle for all requests.
- Changed link to new documentation.

## 1.1.5 - 2021-06-16

### Fixed

- If you use a volume to store the images, the first time displaying the images failed.
- In a scenario, where the image files already exists on the volume but without an asset entry in Craft, the files on the volume will be deleted and downloaded again.

## 1.1.4 - 2021-06-11

### Fixed

- In some cases, you get the old tag structure. So we accept both now.

## 1.1.3 - 2021-06-09

### Fixed

- Instagram has changed the structure of the tag data. We have updated the code accordingly.

## 1.1.2 - 2021-05-12

### Changed

- We made the plugin compatible to older Craft versions again. Changed the required version back to >= 3.0.0.

## 1.1.1 - 2021-04-29

### Fixed

- We now require Craft >= 3.5.0.

## 1.1.0 - 2021-04-29

> {note} Since the end of April 2021, Instagram sets the "cross-origin-resource-policy" header to "same-origin" to all their images, which means that your browser is not allowed to load the images inside another website which is not "instagram.com". Starting with this release of the plugin we download, store and serve the images locally. This may have an impact on your website, and you should read the sections "[Local storage](https://github.com/codemonauts/craft-instagram-feed#local-storage)" and "[Blocked requests](https://github.com/codemonauts/craft-instagram-feed#blocked-requests)" carefully.
### Added

- Downloading and storing the Instagram images locally to either Craft's storage path or a volume and path you can configure.
- New keys `imageSource` and `thumbnailSource` in the array of posts, that hold the original image URLs from Instagram.
- New keys `imageSource` and `thumbnailSource` in the array of posts, that hold the original image URLs from Instagram.
- New key `asset` in the array of posts, that is an asset element of the Instagram image stored on a volume (only available when using a volume to store the image).

### Changed

- The keys `src`, `thumbnail` and `image` in the array of posts now have URLs pointing to your local copy of the images, which the plugin has downloaded and stored on your server.

## 1.0.7 - 2021-02-26

### Fixed
- Fixed videos without information about having an audio.

- Fixed videos without information about having an audio.

## 1.0.6 - 2021-02-16

### Added

- Enable environment variables for setting username (thanks to @niektenhoopen)
- Add rel noopener and noreferrer properties to links in the README (thanks to @JayBox325)
- Add full image URL attribute.
- Add hasAudio attribute.

### Changed

- Prevent request storm if no items are cached and the request failed.
- Set default timeout for requests from 5 to 10 seconds.

### Fixed

- Fixed background color of icon
- Add trailing slash to all requests
- Prevent empty user agent strings
- Fixed some typos
- Catch all exceptions from Guzzle requests

## 1.0.5 - 2020-04-15

### Added

- Switch to write a dump file of the response from Instagram
- Switch to use a proxy (beta)
- Switch to use a proxy (beta)

### Changed

- Improve documentation

### Fixed

- HTTP headers send with file_get_contents

## 1.0.4 - 2019-09-15

### Fixed

- Settings in CP could not be saved due to a validation rule.
- Handle Instagram error response and return empty feed.
- Fixed timeout for file stream (float not microseconds).

## 1.0.3 - 2019-09-14

### Added

- Timestamps of the photos (thanks to @devotoare)
- Timeout fetching the Instgram page, default to 5 seconds, can be changed in the config file (thanks to @mhayes14)
- Support for hashtags (thanks to @JeroenOnstuimig)
Expand All @@ -121,20 +152,28 @@
- Debugging Output (log level debug)

### Fixed

- Some typos (thanks to @ryanpcmcquen)

## 1.0.2 - 2019-05-20

### Added

- Captions of posts

## 1.0.1 - 2019-04-14

### Added

- Overwrite account name on function call
- Add some more logging

### Changed

- Cache account data by account name

## 1.0.0 - 2019-04-06

### Added

- Initial release
21 changes: 10 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ A plugin for Craft CMS that helps you get your Instagram feed data.

If you want to add your (or someone else) Instagram feed on your site, you can use this plugin to fetch and cache the feed. It returns the image source, the number of likes and comments and the shortcode of the posts.

This only works with **public** profiles.
This only works with **public** profiles.

## Requirements

* Craft CMS >= 4.0.0
* Craft CMS >= 4.0.0

## Installation

Expand All @@ -21,27 +21,26 @@ Open your terminal and go to your Craft project:
``` shell
cd /path/to/project
composer require codemonauts/craft-instagram-feed
./craft install/plugin instagramfeed
./craft plugin/install instagramfeed
```

Switch to the settings page in the control panel and enter the name of the Instagram account you want to fetch.

You can also configure a volume where the images are stored locally.
You can also install the plugin via the Plugin Store in the Craft Control Panel.

## Documentation

You find the plugin documentation [here](https://plugins.codemonauts.com/plugins/instagramfeed/Introduction.html).

## Blocked requests

As you know, Instagram is a Walled Garden and they are not very happy to see *their* data on other sites. And they are heavily working on blocking requests not coming from their platforms. So something can break in this plugin at anytime, when trying to fetch the feed.
As you know, Instagram is a Walled Garden, and they are not very happy to see *their* data on other sites. And they are heavily working on blocking requests not coming from their platforms. So something can break in this plugin at anytime, when trying to fetch the feed.

Known actions from Instagram:

* 2018, disabling the old, public API.
* March 2020, disabling the token authentication for their new API.
* April 2020, blocking IP addresses from IP ranges not used for client access.
* April 2021, using "cross-origin-resource-policy" with "same-site" to block browsers from loading images inside another website which is not "instagram.com".
* 2018, disabling the old, public API.
* March 2020, disabling the token authentication for their new API.
* April 2020, blocking IP addresses from IP ranges not used for client access.
* April 2021, using "cross-origin-resource-policy" with "same-site" to block browsers from loading images inside another website which is not "instagram.com".
* June 2022, relaunch of the Instagram website in React. The JSON is now fetched in a second request.

Please be aware, that you use this plugin at your own risk. Please use this plugin only in a fair manner, for example to show the images of your own Instagram account on your website and link them back to the original post on Instagram. This symbiosis should be fine for Instagram.

Expand Down
7 changes: 3 additions & 4 deletions composer.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "codemonauts/craft-instagram-feed",
"description": "Craft CMS plugin to receive Instagram feed data as variable in templates.",
"version": "2.0.0",
"version": "2.0.1",
"type": "craft-plugin",
"keywords": [
"craft",
Expand All @@ -23,9 +23,8 @@
"issues": "https://github.com/codemonauts/craft-instagram-feed/issues"
},
"require": {
"craftcms/cms": "^4.0.0-alpha.1",
"ext-json": "*",
"php": "^8.0"
"craftcms/cms": "^4.0.0",
"ext-json": "*"
},
"autoload": {
"psr-4": {
Expand Down
16 changes: 16 additions & 0 deletions src/InstagramFeed.php
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,11 @@ public function init()
];
});
}

// Prefetch account after save settings
Event::on(Plugin::class, Plugin::EVENT_AFTER_SAVE_SETTINGS, function () {
InstagramFeed::getInstance()->instagramService->getFeed();
});
}

/**
Expand Down Expand Up @@ -120,4 +125,15 @@ protected function settingsHtml(): ?string
]
);
}

/**
* Returns the Instagram service component.
*
* @return InstagramService
* @throws \yii\base\InvalidConfigException
*/
public function getInstagramService(): InstagramService
{
return $this->get('instagramService');
}
}
49 changes: 45 additions & 4 deletions src/services/InstagramService.php
Original file line number Diff line number Diff line change
Expand Up @@ -91,10 +91,11 @@ public function getFeed(string $accountOrTag = null): array
}

if (empty($cachedItems)) {
// If the cache is empty (e.g. first request ever) and the request fails, we are stopping requests for 15 minutes.
Craft::info('Cache is empty and no items could be fetched. Stopping requests for 15 minutes.', 'instagramfeed');
// If the cache is empty (e.g. first request ever) and the request fails, we are stopping requests for some time.
$waitTime = $this->canUseProxy() ? 10 : 900;
Craft::info('Cache is empty and no items could be fetched. Stopping requests for ' . $waitTime . ' seconds.', 'instagramfeed');
$cacheService->set('instagram_data_' . $hash, [], 2592000, $dependency);
$cacheService->set('instagram_update_error_' . $hash, true, 900, $dependency);
$cacheService->set('instagram_update_error_' . $hash, true, $waitTime, $dependency);

return [];
}
Expand All @@ -120,11 +121,20 @@ private function getInstagramAccountData(string $account): array
$html = $this->fetchInstagramPage($account . '/');

if (null === $html) {
Craft::error('Instagram profile data could not be fetched. Wrong account name or not a public profile.', 'instagramfeed');
Craft::error('Instagram profile data could not be fetched.', 'instagramfeed');

return [];
}

if ($this->canUseProxy()) {
$obj = $this->parseProxyResponse($html);
if (false === $obj) {
return [];
}

return $this->flattenMediaArray($obj['data']['user']['edge_owner_to_timeline_media']['edges'], self::STRUCTURE_VERSION_1);
}

$obj = $this->parseInstagramResponse($html);
if (empty($obj)) {
return [];
Expand Down Expand Up @@ -165,6 +175,15 @@ private function getInstagramTagData(string $tag): array
return [];
}

if ($this->canUseProxy()) {
$obj = $this->parseProxyResponse($html);
if (false === $obj) {
return [];
}

return $this->flattenMediaArray($obj['data']['recent']['sections'], self::STRUCTURE_VERSION_2);
}

$obj = $this->parseInstagramResponse($html);
if (empty($obj)) {
return [];
Expand Down Expand Up @@ -262,6 +281,18 @@ private function fetchInstagramPage(string $path): ?string
return (string)$response->getBody();
}

/**
* Function to parse the response body from the proxy.
*
* @param string $response
*
* @return mixed
*/
private function parseProxyResponse(string $response)
{
return json_decode($response, true);
}

/**
* Function to parse the response body from Instagram
*
Expand Down Expand Up @@ -500,4 +531,14 @@ private function populateImages(array $items): array

return $items;
}

/**
* Whether the plugin can use the proxy.
*
* @return bool
*/
public function canUseProxy(): bool
{
return (InstagramFeed::$settings->useProxy && InstagramFeed::$settings->proxyKey !== '');
}
}

0 comments on commit b82407f

Please sign in to comment.