Last active
October 23, 2020 19:06
-
-
Save thiagobraga/0794a33f908eef48d590d19d95fe5e75 to your computer and use it in GitHub Desktop.
Get media from the new Instagram API (July 2020)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Get instagram photos with Instagram API. | |
* | |
* The Instagram API has a limit of 240 requests per hour. With that, | |
* it was necessary to save the responses in jsonbox.io free service to serve | |
* the contents within that 1 hour. LocalStorage is also used to store the | |
* response in user browser, making access to the website faster. | |
*/ | |
(async () => { | |
let photos; | |
const JSONBOX = 'https://jsonbox.io/box_<YOUR_BOX_ID>'; | |
const INSTAGRAM_API = 'https://graph.instagram.com'; | |
const TOKEN = '<YOUR_VERY_LONG_INSTAGRAM_TOKEN>'; | |
const REFRESH_TOKEN = `${INSTAGRAM_API}/refresh_access_token?grant_type=ig_refresh_token&access_token=${TOKEN}`; | |
const USER_ID = '<USER_ID_OBTAINED_IN_DEBUG_TOOLS>'; | |
const fields = 'media_url,permalink,media_type,caption'; | |
// Check LocalStorage for item 'instagram-photos' | |
const localPhotos = localStorage.getItem('instagram-photos'); | |
/** | |
* Render the HTML in the site with obtained photos. | |
*/ | |
const render = (photos) => { | |
const html = /* html */ ` | |
<ul class="slides"> | |
${photos | |
.filter((media) => media.media_url.indexOf('video') === -1) | |
.map((item) => /*html*/ ` | |
<li> | |
<a href="${item.permalink}" target="_blank" rel="noreferrer noopener"> | |
<img src="${item.media_url}" | |
class="instagram-photo" | |
alt="Instagram Photo" | |
width="480" | |
height="480" /> | |
</a> | |
</li> | |
`).join('') | |
} | |
</ul> | |
`; | |
document.querySelector('.container').innerHTML = html; | |
}; | |
/** | |
* Check LocalStorage for previous downloaded media. | |
* Also the 'last-request' is used to compare the time. | |
*/ | |
const checkLocalStorage = () => { | |
let photos; | |
const currentTime = new Date().getTime(); | |
const lastRequest = localStorage.getItem('last-request'); | |
const timeCalc = (currentTime - lastRequest) / 36e5; | |
// If time expired, a new request should be made. | |
// In other words, if the difference is higher than 1 hour. | |
photos = timeCalc > 1 ? [] : JSON.parse(localPhotos); | |
return photos; | |
}; | |
/** | |
* Make a request to the jsonbox.io service endpoint | |
* to obtain the stored photos in JSON format. | |
* If JSON is empty, a new request to Instagram API should be made. | |
*/ | |
const checkJsonBox = async () => { | |
const { data: [result] } = await axios.get(JSONBOX); | |
let { photos, _createdOn } = result; | |
const createdOn = new Date(_createdOn).getTime(); | |
const currentTime = new Date().getTime(); | |
const timeCalc = (currentTime - createdOn) / 36e5; | |
// If time expired, a new request should be made. | |
// In other words, if the difference is higher than 1 hour. | |
if (timeCalc > 1) { | |
// But we need to empty the array from jsonbox.io | |
await axios.post(JSONBOX, { photos: [] }); | |
// And reset photos array, so the script will call the Instagram method. | |
photos = []; | |
} | |
return photos; | |
}; | |
/** | |
* Refresh Instagram token after each request. | |
*/ | |
const refreshToken = async () => await axios.get(REFRESH_TOKEN); | |
/** | |
* Get photos from Instagram API after all tests failed. | |
*/ | |
const getInstagramPhotos = async () => { | |
let photos = []; | |
try { | |
const currentTime = new Date().getTime(); | |
const { data } = await axios.get( | |
`${INSTAGRAM_API}/${USER_ID}?fields=media&access_token=${TOKEN}`, | |
); | |
const { data: response } = data.media; | |
const promises = response.map(async (item) => { | |
const { data } = await axios.get( | |
`${INSTAGRAM_API}/${item.id}?fields=${fields}&access_token=${TOKEN}`, | |
); | |
const { media_url, permalink } = data; | |
return { media_url, permalink }; | |
}); | |
// Wait until all promises resolve. | |
photos = await Promise.all(promises); | |
// Save results in localStorage avoiding the limitation | |
// of Instagram Graph API. | |
localStorage.setItem('instagram-photos', JSON.stringify(photos)); | |
localStorage.setItem('last-request', currentTime); | |
// Save in jsonbox.io too | |
await axios.post(JSONBOX, { photos }); | |
// Refresh token | |
refreshToken(); | |
} catch (error) { | |
console.error('Unable to retrieve photos. Reason: ' + error.toString()); | |
} finally { | |
return photos; | |
} | |
}; | |
// If the key does not exist, the remaining steps must be checked | |
// before making a new request to the Instagram API. | |
if (localPhotos) photos = checkLocalStorage(); | |
if (!localPhotos || photos.length === 0) photos = await checkJsonBox(); | |
if (photos && photos.length === 0) photos = await getInstagramPhotos(); | |
// Finally we call the render function. | |
render(photos); | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment