Skip to content

Commit affe7c1

Browse files
author
jlengstorf
committed
Major code cleanup. Added a bunch more info to the README.
1 parent c993740 commit affe7c1

File tree

5 files changed

+190
-156
lines changed

5 files changed

+190
-156
lines changed

README.md

+38-2
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,51 @@ This is the demo application that will be built during [Jason Lengtorf][1]'s wor
66
using [Instagram's API][3] and [Pusher][4].
77

88

9+
Demo
10+
----
11+
12+
A live demo of this code is available at http://filive-rtws.aws.af.cm/
13+
14+
915
Walkthrough
1016
-----------
1117

1218
To build this app, you'll need to run through the following steps:
1319

14-
1. Set up a live dev environment (AppFog is great if you don't have access to
15-
your own)
20+
1. Set up a live dev environment ([AppFog][5] is a quick and free option if
21+
you don't have access to your own server)
1622
1. Register a new app with Instagram
1723
1. Register a new app with Pusher
24+
1. Subscribe to a tag on Instagram
25+
26+
27+
### Choose Your Tag Wisely
28+
29+
Originally, this demo used `#selfie`, but so many selfies are posted on
30+
Instagram that the API limit of 5000 requests per hour was maxed out within
31+
minutes. Additionally, looking at the `#selfie` feed made me feel like a creepy
32+
old man.
33+
34+
35+
### Adding a Subscription
36+
37+
Add a subscription to the tag `#catstagram` by executing the following command
38+
in a terminal:
39+
40+
curl -F 'client_id=YOUR_CLIENT_ID' \
41+
-F 'client_secret=YOUR_CLIENT_SECRET' \
42+
-F 'object=tag' \
43+
-F 'aspect=media' \
44+
-F 'object_id=catstagram' \
45+
-F 'callback_url=http://YOURREDIRECTURI.com/' \
46+
https://api.instagram.com/v1/subscriptions/
47+
48+
49+
### Deleting a Subscription
50+
51+
Remove all subscriptions by executing the following command in a terminal:
1852

53+
curl -X DELETE 'https://api.instagram.com/v1/subscriptions?client_secret=YOUR_CLIENT_SECRET&client_id=YOUR_CLIENT_ID&object=all'
1954

2055

2156
Copyright and license
@@ -40,4 +75,5 @@ the License.
4075
[2]: http://futureinsightslive.com/las-vegas-2013/
4176
[3]: http://instagram.com/developer/
4277
[4]: http://pusher.com/
78+
[5]: https://www.appfog.com/
4379

inc/config-example.inc.php

+4-3
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,13 @@
44
error_reporting(E_ALL^E_STRICT);
55
ini_set('display_errors', 1);
66

7-
session_start();
8-
97
// Instagram API credentials
108
$ig_client_id = '';
119
$ig_secret = '';
12-
$ig_login_uri = 'http://example.com//login.php';
10+
$ig_login_uri = 'http://example.com/login.php';
11+
12+
// Tag to retrieve
13+
$tag = 'catstagram';
1314

1415
// Pusher API credentials
1516
$pusher_key = '';

index.php

+32-150
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,18 @@
88
exit;
99
}
1010

11+
// Catches realtime updates from Instagram
1112
if ($_SERVER['REQUEST_METHOD']==='POST') {
13+
1214
// Instantiates Pusher PHP API
1315
require 'lib/Pusher.php';
1416

17+
// Retrieves the POST data from Instagram
1518
$update = file_get_contents('php://input');
16-
1719
$photos = json_decode($update);
18-
if (is_array($photos)) {
19-
$length = count($photos);
20-
}
2120

22-
if ($length>0) {
21+
// If one or more photos has been posted, notify all clients
22+
if (is_array($photos) && ($length=count($photos))>0) {
2323
$pusher = new Pusher($pusher_key, $pusher_secret, $pusher_app_id);
2424
$pusher->trigger(
2525
'photos',
@@ -29,40 +29,17 @@
2929
)
3030
);
3131
}
32+
3233
}
3334

34-
// Get most recent IG photos
35+
// Retrieves the access token from the query string
3536
$token = isset($_GET['access_token']) ? $_GET['access_token'] : NULL;
36-
$tag = isset($_GET['tag']) ? $_GET['tag'] : 'instacat';
37-
38-
$api_url = 'https://api.instagram.com/v1/tags/'
39-
. $tag . '/media/recent?count=16&access_token=' . $token;
40-
41-
$page_url = 'http://' . $_SERVER['SERVER_NAME']
42-
. dirname($_SERVER['REQUEST_URI'])
43-
. '/?access_token=' . $token
44-
. '&tag=' . $tag;
45-
46-
$ch = curl_init($api_url);
47-
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
48-
$response = json_decode(curl_exec($ch));
49-
$photos = property_exists($response, 'data') ? $response->data : array();
5037

51-
/*
52-
53-
https://api.instagram.com/v1/tags/nofilter/media/recent
54-
55-
curl -F 'client_id=6019cd09a31d488eab0a8e072f408415' \
56-
-F 'client_secret=d1fcd47c601e4d80912f5168fc8efaa7' \
57-
-F 'object=tag' \
58-
-F 'aspect=media' \
59-
-F 'object_id=catstagram' \
60-
-F 'callback_url=http://demo.copterlabs.com/filive/workshop/' \
61-
https://api.instagram.com/v1/subscriptions/
62-
63-
curl -X DELETE 'https://api.instagram.com/v1/subscriptions?client_secret=d1fcd47c601e4d80912f5168fc8efaa7&client_id=6019cd09a31d488eab0a8e072f408415&object=all'
64-
65-
*/
38+
// Generates the login URL to authorize the app
39+
$login_url = 'https://api.instagram.com/oauth/authorize/'
40+
. '?client_id=' . $ig_client_id
41+
. '&redirect_uri=' . $ig_login_uri
42+
. '&response_type=code'
6643

6744
?>
6845
<!doctype html>
@@ -80,7 +57,18 @@
8057

8158
<body>
8259

83-
<?php if ($token!==NULL): ?>
60+
<?php if ($token===NULL): ?>
61+
62+
<header>
63+
<h1>Log in to start playing with realtime!</h1>
64+
</header>
65+
66+
<article>
67+
<a href="<?=$login_url?>"
68+
class="login button">Login &rarr;</a>
69+
</article>
70+
71+
<?php else: ?>
8472

8573
<header>
8674
<h1>Photos tagged with #<?=$tag?></h1>
@@ -98,147 +86,41 @@ class="button"
9886
</div>
9987

10088
<ul id="photos">
101-
102-
<?php //foreach ($photos as $photo): ?>
10389
<li class="loading">Loading&hellip;</li>
104-
<!-- <li>
105-
<a href="<?=$photo->link?>">
106-
<img src="<?=$photo->images->thumbnail->url?>"
107-
alt="<?=(empty($photo->caption)) ? $photo->caption->text : NULL ?>"
108-
data-id="<?=$photo->id?>" />
109-
<strong>Photo by <?=$photo->user->username?></strong>
110-
</a>
111-
</li> -->
112-
<?php //endforeach; ?>
113-
11490
</ul><!--/#photos-->
11591

11692
</article>
11793

118-
<?php else: ?>
119-
120-
<header>
121-
<h1>Log in to start playing with realtime!</h1>
122-
</header>
123-
124-
<article>
125-
<a href="https://api.instagram.com/oauth/authorize/?client_id=<?=$ig_client_id?>&amp;redirect_uri=http://demo.copterlabs.com/filive/workshop/login.php&amp;response_type=code"
126-
class="login button">Login &rarr;</a>
127-
</article>
128-
12994
<?php endif; ?>
13095

13196
<footer>
13297
<p>
13398
This demo was created by
134-
<a href="http://www.lengstorf.com/">Jason Lengstorf</a> for use at the
135-
realtime workshop at Future Insights Live 2013. It is released under the
136-
MIT License.
99+
<a href="http://www.lengstorf.com/">Jason Lengstorf</a> for use in the
100+
realtime workshop at Future Insights Live 2013. All photos belong to
101+
their respective owners.
137102
</p>
138103
</footer>
139104

140105
<script src="http://code.jquery.com/jquery-2.0.0.min.js"></script>
141106
<script src="http://js.pusher.com/2.0/pusher.min.js"></script>
142107
<script>
143108

144-
jQuery(function($){
145-
146-
// Enable pusher logging - don't include this in production
109+
// Enables pusher logging - don't include this in production
147110
Pusher.log = function(message) {
148111
if (window.console && window.console.log) window.console.log(message);
149112
};
150113

151114
// Flash fallback logging - don't include this in production
152115
WEB_SOCKET_DEBUG = true;
153116

154-
var newcount = 0,
155-
pusher = new Pusher('<?=$pusher_key?>'),
117+
// Initializes Pusher (done inline to use PHP for config variables)
118+
var pusher = new Pusher('<?=$pusher_key?>'),
156119
channel = pusher.subscribe('photos'),
157-
photos = $('photos'),
158-
min_ID = photos.data('next-min-ID'),
159-
load_photos = function() {
160-
// Hides the notification
161-
$("#count-bar").addClass("hidden");
162-
163-
$.getJSON(
164-
'https://api.instagram.com/v1/tags/<?=$tag?>/media/recent?callback=?',
165-
{
166-
'access_token': '<?=$token?>',
167-
'count': 16,
168-
'min_id': min_ID
169-
}
170-
)
171-
.done(function(response){
172-
var new_photos = response.data,
173-
pagination = response.pagination,
174-
delay = 0,
175-
anim_speed = 200;
176-
177-
// Removes the loading LI if present
178-
$("#photos").find('.loading').hide(400).delay(400).remove();
179-
180-
// Resets the new photo count
181-
newcount = 0;
182-
183-
// Sets the new min ID for loading images
184-
min_ID = pagination.next_min_id;
185-
186-
for (x in new_photos) {
187-
var photoCont = $("#photos"),
188-
photo = new_photos[x],
189-
caption = (photo.caption!==null) ? photo.caption.text : '';
190-
191-
//TODO: Make the captions show up and fix delay
192-
193-
$('<img />', {
194-
src: photo.images.thumbnail.url,
195-
alt: caption,
196-
load: function(){
197-
var link = $('<a />', {
198-
href: photo.link,
199-
html: this
200-
})
201-
.css({opacity: 0})
202-
.delay(delay)
203-
.prependTo($("#photos"))
204-
.append($('<strong />'), {
205-
text: 'Photo by ' + photo.user.username
206-
})
207-
.wrap('<li />')
208-
.animate({ opacity: 1 }, anim_speed);
209-
}
210-
});
211-
212-
delay += anim_speed;
213-
}
214-
})
215-
.error(function(data){
216-
console.log(data);
217-
});
218-
};
219-
220-
channel.bind('new-photo', function(data){
221-
222-
newcount += data.newcount;
223-
224-
var plural = (newcount===1) ? 'photo' : 'photos';
225-
phrase = newcount+' new '+plural+' uploaded.';
226-
227-
$('#count-bar').removeClass('hidden').find('#count').text(phrase);
228-
229-
});
230-
231-
$("#image-loader").bind('click', function(event){
232-
event.preventDefault();
233-
234-
load_photos();
235-
});
236-
237-
load_photos();
238-
239-
});
120+
tag = '<?=$tag?>'; // For PHP-powered tag selection
240121

241122
</script>
123+
<script src="js/main.js"></script>
242124

243125
</body>
244126

0 commit comments

Comments
 (0)