Jump to content
nbcommunication

InstagramBasicDisplayApi

Recommended Posts

54 minutes ago, nbcommunication said:

No, I think echoing as you are doing would probably be faster if anything. Basically no difference

Cool! Thanks! 🙂 

54 minutes ago, nbcommunication said:

I'm going to look into making the pagination more available through the module tomorrow.

Beautiful!

55 minutes ago, nbcommunication said:

I think that may have been from the previous API. This one returns the first 24 items [...]

Good to know!

54 minutes ago, nbcommunication said:

<?php $images = $instagram->getMedia(89); echo count($images) . "<br>" . print_r($images, 1);

returns = 

ProcessWire\WireArray Object
(
    [count] =&gt; 89
    [items] =&gt; Array
        (
            [WireData:0] =&gt; 17909280568424854
            [WireData:1] =&gt; 18121444630076805
            [WireData:2] =&gt; 18099159694143228
            [WireData:3] =&gt; 17883854266519759
            [WireData:4] =&gt; 17854176994877232
            [WireData:5] =&gt; 18055223719211749
            [WireData:6] =&gt; 17865563617641437
            [WireData:7] =&gt; 17853880954804716
            [WireData:8] =&gt; 17914593256381694
            [WireData:9] =&gt; 17860300231719969
            [WireData:10] =&gt; 18017777869257089
            [WireData:11] =&gt; 18019319182253256
            [WireData:12] =&gt; 17847252025839832
            [WireData:13] =&gt; 18036204127233891
            [WireData:14] =&gt; 18122234449006372
            [WireData:15] =&gt; 17917004923367534
            [WireData:16] =&gt; 17854499389726168
            [WireData:17] =&gt; 17852987293735761
            [WireData:18] =&gt; 18086538826081818
            [WireData:19] =&gt; 17866962334577860
            [WireData:20] =&gt; 18120750871023389
            [WireData:21] =&gt; 18009153073268946
            [WireData:22] =&gt; 17849294431747827
            [WireData:23] =&gt; 17901084034396625
            [WireData:24] =&gt; 18094452511099675
            [WireData:25] =&gt; 17847189019719414
            [WireData:26] =&gt; 17854334599578989
            [WireData:27] =&gt; 18107613148049776
            [WireData:28] =&gt; 17909512951361240
            [WireData:29] =&gt; 18104916640032595
            [WireData:30] =&gt; 18105513970043998
            [WireData:31] =&gt; 18066704767130489
            [WireData:32] =&gt; 17881743565421950
            [WireData:33] =&gt; 17957414410288932
            [WireData:34] =&gt; 17957563855294908
            [WireData:35] =&gt; 18061218313179032
            [WireData:36] =&gt; 17845018267605780
            [WireData:37] =&gt; 17860652530488128
            [WireData:38] =&gt; 18008583064246673
            [WireData:39] =&gt; 18087603124064192
            [WireData:40] =&gt; 17849476189531758
            [WireData:41] =&gt; 18046166611199390
            [WireData:42] =&gt; 17848414930558047
            [WireData:43] =&gt; 17971295623301665
            [WireData:44] =&gt; 18089590891035103
            [WireData:45] =&gt; 17872427797427060
            [WireData:46] =&gt; 18087955213016216
            [WireData:47] =&gt; 17844902065536403
            [WireData:48] =&gt; 17844973564532788
            [WireData:49] =&gt; 17859331249452842
            [WireData:50] =&gt; 17849882830471152
            [WireData:51] =&gt; 18075170245064821
            [WireData:52] =&gt; 17942550430293736
            [WireData:53] =&gt; 17966881903273180
            [WireData:54] =&gt; 17965161424273612
            [WireData:55] =&gt; 17898185860336217
            [WireData:56] =&gt; 18041889235148605
            [WireData:57] =&gt; 18075502267046552
            [WireData:58] =&gt; 18007052467216993
            [WireData:59] =&gt; 17886482302359660
            [WireData:60] =&gt; 17871858511389658
            [WireData:61] =&gt; 17869022899360249
            [WireData:62] =&gt; 18036545284117191
            [WireData:63] =&gt; 17872542331346319
            [WireData:64] =&gt; 18008081158196147
            [WireData:65] =&gt; 18050794615051665
            [WireData:66] =&gt; 17861485243368787
            [WireData:67] =&gt; 17865307225357563
            [WireData:68] =&gt; 18039611095079744
            [WireData:69] =&gt; 18048228658019001
            [WireData:70] =&gt; 17986084408204328
            [WireData:71] =&gt; 17873339755334078
            [WireData:72] =&gt; 17880649264316699
            [WireData:73] =&gt; 18019533538130038
            [WireData:74] =&gt; 18020855698187180
            [WireData:75] =&gt; WireData
            [WireData:76] =&gt; WireData
            [WireData:77] =&gt; WireData
            [WireData:78] =&gt; WireData
            [WireData:79] =&gt; WireData
            [WireData:80] =&gt; WireData
            [WireData:81] =&gt; WireData
            [WireData:82] =&gt; WireData
            [WireData:83] =&gt; WireData
            [WireData:84] =&gt; WireData
            [WireData:85] =&gt; WireData
            [WireData:86] =&gt; WireData
            [WireData:87] =&gt; WireData
            [WireData:88] =&gt; WireData
        )

)

 

1 hour ago, nbcommunication said:

How many carousels do you have?

A lot... Out of the 80 showed posts, 46 are carousels.

1 hour ago, nbcommunication said:

Will have another look at this tomorrow. I think it may be useful to have an option to not get the full carousel when using getMedia() as this does seem to be the issue.

Hm.. But I guess that showing carousels shouldn't be an issue? 🤔 Shouldn't it be problemfree to display all of the users carousels?

1 hour ago, nbcommunication said:

getUserAccount() should have the same value for media_count, but it is only updated when getProfile() is called (and an API request is made) [...] I can't think of a situation where it should be used over getProfile().

– Thank you for clearing that up!!  I've adapted my code to your version  😊 

Goodnight from Denmark 🙂 🇩🇰

Share this post


Link to post
Share on other sites

.. well ok just a minor update:

With the API call restriction all maxed out I'm still getting this:

367006132_Skrmbillede2020-03-26kl_01_21_59.thumb.png.59be4e4db2831c0cbd4f60d6822ce87b.png      2139544411_Skrmbillede2020-03-26kl_01_21_42.thumb.png.b92cf18e0eae1e35067f263874a485ec.png

 

Even though It's now

$images = $instagram->getMedia(89);
                    echo count($images) . "<br>" . print_r($images, 1);
                    if(count($images)) { // Should avoid errors if there's no API response?
                        foreach($images as $post) {

 

Share this post


Link to post
Share on other sites

Hi @jonatan,

Thanks for the debug array. Yep there's definitely an issue with asking for more items than there actually is. Will get that sorted.

8 hours ago, jonatan said:

A lot... Out of the 80 showed posts, 46 are carousels.

Each carousel requires a separate API call. That means each request for 80 items (that isn't cached) uses up 50 API calls.

7 hours ago, jonatan said:

With the API call restriction all maxed out I'm still getting this:

The error isn't at that point. Try this:

<?php

switch($post->type) {
  case "VIDEO":
    // ...
    break;
  case "CAROUSEL_ALBUM":
    
    // If the post does not have children, continue without rendering
    if(!$post->children) break;
    
    // ...
    break;
  // ...
}

Cheers,

Chris

  • Like 1

Share this post


Link to post
Share on other sites

Hi @jonatan,

I've managed to get access to an account with 20 items for testing. The "counting" in the module is actually correct, I think the issue is maybe that after the limit is reached the API just returns blank records? Anyway, I've added a little bit of code that removes any items without a media_url before they are returned, which should fix your issue. Code not pushed yet, should be later today.

Cheers,

Chris

  • Thanks 1

Share this post


Link to post
Share on other sites

Hi @jonatan,

Aye lazy loading is proving to be a little tricky, mainly because of caching. I need to think through this more and will get back to it tomorrow.

Cheers,

Chris

  • Thanks 1

Share this post


Link to post
Share on other sites
On 3/26/2020 at 8:31 AM, nbcommunication said:

That means each request for 80 items (that isn't cached) uses up 50 API calls.

Hm but shouldn't the caching be activated by default? It seems that it keeps using API calls... even within the same hour (3600 seconds)?

On 3/26/2020 at 8:31 AM, nbcommunication said:

if(!$post->children) break;

– Implemented! Thanks!!!

21 hours ago, nbcommunication said:

Anyway, I've added a little bit of code that removes any items without a media_url

Nice! The module's updated now.

19 hours ago, nbcommunication said:

Aye lazy loading is proving to be a little tricky, mainly because of caching. I need to think through this more and will get back to it tomorrow.

So happy that you're on it! Can't wait to see what you come up with. Fingers crossed 😃🤞

All the very best,

Jonatan

Share this post


Link to post
Share on other sites

Hi @jonatan,

I'm making good progress on this but not finished yet. Discovered that there's a hidden "limit" API option which has necessitated a bit of a rewrite.

May get to it this weekend (weather is looking good though, so might be out in the garden!), if not on Monday.

Cheers,

Chris

  • Like 1

Share this post


Link to post
Share on other sites

@nbcommunication Hi Criss!

Sounds interesting! 😄

No worries though. Nothing very urgent 😊 

If so, enjoy the garden! 🌱🌿 It's been great in Denmark as well lately! ☀️

All the very best,

Jonatan

Share this post


Link to post
Share on other sites

Hi @jonatan,

I've been able to pick away at this over the weekend... too cold yet to plant tatties!

With the discovery of the hidden limit option in the API, I had to rewrite some of the module, but everything should just work the same, if not even better...

However, I'm not sure it'll help too much with API rate limiting in your case, as each carousel album is still a separate API call. There is now the option to prevent the "children" (the rest of the album carousel images) from being retrieved:

<?php
$instagram = $modules->get("InstagramBasicDisplayApi");
$items = $instagram->getMedia(["children" => false]);

When working with this over the weekend, I kept an eye on the rate limiting page and it did get nudged frequently, but didn't go beyond 30% used. The account I was using for testing only had a few carousels though.

I've also been able to implement "lazy loading". The example I've added to the README is based on the getMedia() example, using UIkit's javascript utilities. I've attached a short clip of how this looks.

Here's how it might work using Bootstrap/jQuery:

In your template file:

<?php

$instagram = $modules->get("InstagramBasicDisplayApi"); // The pagination cursor is reset if the request is not AJAX, e.g. when the page is loaded.

if($config->ajax) {
	header("Content-Type: application/json");
	echo $instagram->getMedia(); // ["json" => true] is inferred by $config->ajax
	die();
}

echo "<div id='instagram' class='row'></div>";

In your javascript:

// Totally untested!!!!
var instagram = {

	$el: {}, // Where the items go
	$loading: {}, // The loading spinner
	total: 0, // The total number of items

	init: function() {

		this.$el = $("#instagram");
		if(!this.$el.length) return;

		// Add the spinner
		this.$el.after("<div id='instagram-loading'>...Your choice of spinner!</div>");
		this.$loading = $("#instagram-loading");
		this.$loading.hide();

		// Get the first batch of items
		this.get();
	},

	get: function() {

		var this$1 = this;

		// Show spinner
		this$1.$loading.show();

		// Request
		$.getJSON(window.location.href, function(data) {

			// Hide spinner
			this$1.$loading.hide();

			if(!$.isArray(data) || !data.length) return; // If no items do not render

			var items = [];
			data.forEach(function(item, index) {

				switch(item.type) {
					case "VIDEO":
						items.push(this$1.renderItem(item.poster, item.alt, item.src, index));
						break;
					case "CAROUSEL_ALBUM":
						
						var out = "";
						for(var i = 0; i < item.children.length; i++) {
							var src = item.children[i].src;
							out += "<a class='carousel-item' data-fancybox='gallery-ig' data-height='600'  data-caption='" + item.alt + "' href='" + src + "'>" +
								"<div style='background-image: url(" + src + ")' class='pics'></div>" + 
							"</a>";
						}

						items.push(
							"<div data-interval='3000' class='carousel slide carousel-fade col-4 p-3 pics' data-ride='carousel' id='instagram-item-" + (this$1.total + index) + "'>" + 
								"<div class='carousel-inner'>" + 
									out + 
									"<a class='carousel-control-prev' href='#_{$post->id}' role='button' data-slide='prev'>" +
										"<span class='carousel-control-icon-bg' aria-hidden='true'></span>" +
										"<span class='carousel-control-prev-icon' aria-hidden='true'></span>" +
										"<span class='sr-only'>Previous</span>" +
									"</a>" +
									"<a class='carousel-control-next' href='#_{$post->id}' role='button' data-slide='next'>" +
										"<span class='carousel-control-icon-bg' aria-hidden='true'></span>" +
										"<span class='carousel-control-next-icon' aria-hidden='true'></span>" +
										"<span class='sr-only'>Next</span>" +
									"</a>" +
								"</div>" + 
							"</div>"
						);	
									  
						break;
					default: // IMAGE
						items.push(this$1.renderItem(item.src, item.alt, item.src, index));
						break;
				}
			});

			var count = items.length;
			if(count) {

				// Append items to the container
				this$1.$el.append(items.join(""));

				// Attach listener 
				// No idea if this works!!!
				$(window).on("resize scroll", function() {
					var next = $("#instagram-item-" + (this$1.total + count - (count < 5 ? 1 : 6)));
					if(!next.hasClass("seen") && this$1.inViewport()) {
						next.addClass("seen");
						this$1.get();
					}
				});

				// Update total
				this$1.total = this$1.total + count;
			}
		}, function(e) {
			this$1.$loading.hide();
			console.log(e); // ERROR
		})
	},

	inViewport: function(el) {

		// Untested, got the code from
		// https://medium.com/talk-like/detecting-if-an-element-is-in-the-viewport-jquery-a6a4405a3ea2

		var elementTop = el.offset().top;
		var elementBottom = elementTop + el.outerHeight();
		var viewportTop = $(window).scrollTop();
		var viewportBottom = viewportTop + $(window).height();
		return elementBottom > viewportTop && elementTop < viewportBottom;
	},

	renderItem: function(src, alt, href, index) {
		return "<div class='col-4 p-3 pics' id='instagram-item-" + (this.total + index) + "'>" + 
			"<a data-fancybox='gallery-ig' data-height='600' data-caption='" + alt + "' href='" + href + "'>" + 
				"<div style='background-image: url(" + src + ")' class='pics'>" +
					(src !== href ? "<div class='overlay-video-icon'></div>" : "") +         
				"</div>" + 
			"</a>" +
		"</div>";
	}
};

$(document).ready(function() {
	instagram.init();
});

I've just done the jQuery from memory with the addition of an inViewport function I found online. No idea if it works!

Let me know how you get on!

Cheers,

Chris

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...