From 1d2edc426d883737df7413a2b62985d95a60be2c Mon Sep 17 00:00:00 2001 From: Ishaan Garg <168962484+Ishaang19@users.noreply.github.com> Date: Wed, 15 Oct 2025 21:41:55 +0530 Subject: [PATCH] Issue #8 Login Issue - Not redirect to Api.instagram.com fix #8 --- demos/instagram.html | 269 ++++++++++++-------- src/modules/instagram.js | 514 ++++++++++++++++++++++++--------------- 2 files changed, 487 insertions(+), 296 deletions(-) diff --git a/demos/instagram.html b/demos/instagram.html index a541f4d..2bc0b22 100644 --- a/demos/instagram.html +++ b/demos/instagram.html @@ -1,160 +1,219 @@ - + - - + - - - - + -hello( instagram ) -

hello( instagram )

+ - -
- + -

The button above executes getPhotos()

+ - - // Define an instagram instance - var instagram = hello( 'instagram' ); + - // Trigger login to instagram - instagram.login().then( function(){ + - // Get Profile - instagram.api('me').then( profileHandler, errorHandler); + - // Get user photos - instagram.api('me/photos').then( photosHandler, errorHandler ); +hello( instagram ) - },errorHandler); -} +

hello( instagram )

+ -function profileHandler( r ){ +
- var profile = document.getElementById( 'profile' ); +⚠️ Instagram Basic Display API Notice: - profile.innerHTML = "Connected to instagram as " + r.name; +

Instagram has deprecated their old API. This demo now uses the Instagram Basic Display API which:

-} + - hello( 'instagram' ).api( next ).then( photosHandler, errorHandler ); +

Learn more: Instagram Basic Display API Documentation

- }; -} +
- + -

Set up your client id

+ - +
+ -

Like

+ - +

The button above executes getPhotos()

-

Once photos are loaded, click the photo to 'like'

+ - + + +var profile = document.getElementById( 'profile' ); - \ No newline at end of file +profile.innerHTML = "Connected to Instagram as " + r.name + " (ID: " + r.id + ")"; + + + +} + + + + + +function photosHandler( r ){ + + + +for(var i=0;i + + + +

Set up your client id

+ + + + + + + + + + \ No newline at end of file diff --git a/src/modules/instagram.js b/src/modules/instagram.js index 5079fbc..a3039b4 100644 --- a/src/modules/instagram.js +++ b/src/modules/instagram.js @@ -1,191 +1,323 @@ -(function(hello) { - - hello.init({ - - instagram: { - - name: 'Instagram', - - oauth: { - // See: http://instagram.com/developer/authentication/ - version: 2, - auth: 'https://instagram.com/oauth/authorize/', - grant: 'https://api.instagram.com/oauth/access_token' - }, - - // Refresh the access_token once expired - refresh: true, - - scope: { - basic: 'basic', - photos: '', - friends: 'relationships', - publish: 'likes comments', - email: '', - share: '', - publish_files: '', - files: '', - videos: '', - offline_access: '' - }, - - scope_delim: ' ', - - base: 'https://api.instagram.com/v1/', - - get: { - me: 'users/self', - 'me/feed': 'users/self/feed?count=@{limit|100}', - 'me/photos': 'users/self/media/recent?min_id=0&count=@{limit|100}', - 'me/friends': 'users/self/follows?count=@{limit|100}', - 'me/following': 'users/self/follows?count=@{limit|100}', - 'me/followers': 'users/self/followed-by?count=@{limit|100}', - 'friend/photos': 'users/@{id}/media/recent?min_id=0&count=@{limit|100}' - }, - - post: { - 'me/like': function(p, callback) { - var id = p.data.id; - p.data = {}; - callback('media/' + id + '/likes'); - } - }, - - del: { - 'me/like': 'media/@{id}/likes' - }, - - wrap: { - me: function(o) { - - formatError(o); - - if ('data' in o) { - o.id = o.data.id; - o.thumbnail = o.data.profile_picture; - o.name = o.data.full_name || o.data.username; - } - - return o; - }, - - 'me/friends': formatFriends, - 'me/following': formatFriends, - 'me/followers': formatFriends, - 'me/photos': function(o) { - - formatError(o); - paging(o); - - if ('data' in o) { - o.data = o.data.filter(function(d) { - return d.type === 'image'; - }); - - o.data.forEach(function(d) { - d.name = d.caption ? d.caption.text : null; - d.thumbnail = d.images.thumbnail.url; - d.picture = d.images.standard_resolution.url; - d.pictures = Object.keys(d.images) - .map(function(key) { - var image = d.images[key]; - return formatImage(image); - }) - .sort(function(a, b) { - return a.width - b.width; - }); - }); - } - - return o; - }, - - 'default': function(o) { - o = formatError(o); - paging(o); - return o; - } - }, - - // Instagram does not return any CORS Headers - // So besides JSONP we're stuck with proxy - xhr: function(p, qs) { - - var method = p.method; - var proxy = method !== 'get'; - - if (proxy) { - - if ((method === 'post' || method === 'put') && p.query.access_token) { - p.data.access_token = p.query.access_token; - delete p.query.access_token; - } - - // No access control headers - // Use the proxy instead - p.proxy = proxy; - } - - return proxy; - }, - - // No form - form: false - } - }); - - function formatImage(image) { - return { - source: image.url, - width: image.width, - height: image.height - }; - } - - function formatError(o) { - if (typeof o === 'string') { - return { - error: { - code: 'invalid_request', - message: o - } - }; - } - - if (o && 'meta' in o && 'error_type' in o.meta) { - o.error = { - code: o.meta.error_type, - message: o.meta.error_message - }; - } - - return o; - } - - function formatFriends(o) { - paging(o); - if (o && 'data' in o) { - o.data.forEach(formatFriend); - } - - return o; - } - - function formatFriend(o) { - if (o.id) { - o.thumbnail = o.profile_picture; - o.name = o.full_name || o.username; - } - } - - // See: http://instagram.com/developer/endpoints/ - function paging(res) { - if ('pagination' in res) { - res.paging = { - next: res.pagination.next_url - }; - delete res.pagination; - } - } - -})(hello); +(function(hello) { + + + +hello.init({ + + + +instagram: { + + + +name: 'Instagram', + + + +oauth: { + +// Instagram Basic Display API + +// See: https://developers.facebook.com/docs/instagram-basic-display-api + +version: 2, + +auth: 'https://www.instagram.com/oauth/authorize/', + +grant: 'https://api.instagram.com/oauth/access_token' + +}, + + + +// Refresh the access_token once expired + +refresh: true, + + + +scope: { + +// Basic Display API scopes + +basic: 'user_profile', + +photos: 'user_media', + +// Deprecated/unsupported scopes + +friends: '', + +publish: '', + +email: '', + +share: '', + +publish_files: '', + +files: '', + +videos: '', + +offline_access: '' + +}, + + + +scope_delim: ',', + + + +// Instagram Basic Display API base URL + +base: 'https://graph.instagram.com/', + + + +get: { + +// Get user profile + +me: 'me?fields=id,username,account_type,media_count', + + + +// Get user's media + +'me/photos': 'me/media?fields=id,caption,media_type,media_url,permalink,thumbnail_url,timestamp,username&limit=@{limit|25}', + + + +// Note: Basic Display API doesn't support friends/followers endpoints + +// These are kept for backwards compatibility but will not work + +'me/friends': function() { + +return false; + +}, + +'me/following': function() { + +return false; + +}, + +'me/followers': function() { + +return false; + +} + +}, + + + +// Basic Display API is read-only, no POST/DELETE operations + +// Removed post and del objects + + + +wrap: { + +me: function(o) { + + + +formatError(o); + + + +if (o && !o.error) { + +// Basic Display API returns data directly, not wrapped in 'data' + +o.id = o.id; + +o.name = o.username; + +// Basic Display API doesn't provide profile_picture in /me endpoint + +// Would need separate call to get profile picture + +o.thumbnail = null; + +} + + + +return o; + +}, + + + +'me/photos': function(o) { + + + +formatError(o); + +paging(o); + + + +if ('data' in o) { + +o.data = o.data.filter(function(d) { + +// Filter for images and videos (carousel albums contain both) + +return d.media_type === 'IMAGE' || d.media_type === 'VIDEO' || d.media_type === 'CAROUSEL_ALBUM'; + +}); + + + +o.data.forEach(function(d) { + +// Map new API fields to old structure for compatibility + +d.name = d.caption || null; + +d.thumbnail = d.thumbnail_url || d.media_url; + +d.picture = d.media_url; + +d.source = d.media_url; + +d.type = d.media_type.toLowerCase(); + +d.created_time = d.timestamp; + +}); + +} + + + +return o; + +}, + + + +'default': function(o) { + +o = formatError(o); + +paging(o); + +return o; + +} + +}, + + + +// Instagram Basic Display API supports CORS + +xhr: false, + + + +// No form + +form: false + +} + +}); + + + +function formatError(o) { + +if (typeof o === 'string') { + +return { + +error: { + +code: 'invalid_request', + +message: o + +} + +}; + +} + + + +// Basic Display API error format + +if (o && o.error) { + +if (typeof o.error === 'object') { + +// Error is already in correct format + +return o; + +} else { + +// Convert error to standard format + +o.error = { + +code: o.error_type || 'request_failed', + +message: o.error_message || o.error + +}; + +} + +} + + + +return o; + +} + + + +// Basic Display API uses cursor-based pagination + +function paging(res) { + +if (res && res.paging) { + +// API already provides paging object with next/previous URLs + +if (res.paging.next) { + +// Extract just the path and query from the full URL + +var next = res.paging.next; + +// Keep the full URL as-is since it's an absolute URL from Graph API + +res.paging = { + +next: next + +}; + +} + +} + +} + + + +})(hello); \ No newline at end of file