This repository has been archived by the owner on Jan 13, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 88
/
helpers.js
114 lines (102 loc) · 3.62 KB
/
helpers.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
var redis = require('redis');
var settings = require('./settings');
/*
Each update that comes from Instagram merely tells us that there's new
data to go fetch. The update does not include the data. So, we take the
geography ID from the update, and make the call to the API.
*/
function processGeography(geoName, update){
var path = '/v1/geographies/' + update.object_id + '/media/recent/';
getMinID(geoName, function(error, minID){
var queryString = "?client_id="+ settings.CLIENT_ID;
if(minID){
queryString += '&min_id=' + minID;
} else {
// If this is the first update, just grab the most recent.
queryString += '&count=1';
}
var options = {
host: settings.apiHost,
// Note that in all implementations, basePath will be ''. Here at
// instagram, this aint true ;)
path: settings.basePath + path + queryString
};
if(settings.apiPort){
options['port'] = settings.apiPort;
}
// Asynchronously ask the Instagram API for new media for a given
// geography.
settings.httpClient.get(options, function(response){
var data = '';
response.on('data', function(chunk){
data += chunk;
});
response.on('end', function(){
try {
var parsedResponse = JSON.parse(data);
} catch (e) {
console.log('Couldn\'t parse data. Malformed?');
return;
}
if(!parsedResponse || !parsedResponse['data']){
console.log('Did not receive data for ' + geoName +':');
console.log(data);
return;
}
setMinID(geoName, parsedResponse['data']);
// Let all the redis listeners know that we've got new media.
var r = redis.createClient(
settings.REDIS_PORT,
settings.REDIS_HOST);
r.publish('channel:' + geoName, data);
r.quit();
});
});
});
}
exports.processGeography = processGeography;
function getMedia(callback){
// This function gets the most recent media stored in redis
var r = redis.createClient(settings.REDIS_PORT, settings.REDIS_HOST);
r.lrange('media:objects', 0, 14, function(error, media){
// Parse each media JSON to send to callback
media = media.map(function(json){return JSON.parse(json);});
callback(error, media);
});
r.quit()
}
exports.getMedia = getMedia;
/*
In order to only ask for the most recent media, we store the MAXIMUM ID
of the media for every geography we've fetched. This way, when we get an
update, we simply provide a min_id parameter to the Instagram API that
fetches all media that have been posted *since* the min_id.
You might notice there's a fatal flaw in this logic: We create
media objects once your upload finishes, not when you click 'done' in the
app. This means that if you take longer to press done than someone else
who will trigger an update on your same geography, then we will skip
over your media. Alas, this is a demo app, and I've had far too
much red bull – so we'll live with it for the time being.
*/
function getMinID(geoName, callback){
var r = redis.createClient(settings.REDIS_PORT, settings.REDIS_HOST);
r.get('min-id:channel:' + geoName, callback);
r.quit();
}
exports.getMinID = getMinID;
function setMinID(geoName, data){
var sorted = data.sort(function(a, b){
return parseInt(b.id) - parseInt(a.id);
});
var nextMinID;
try {
nextMinID = parseInt(sorted[0].id);
var r = redis.createClient(settings.REDIS_PORT, settings.REDIS_HOST);
r.set('min-id:channel:' + geoName, nextMinID);
r.quit();
} catch (e) {
console.log('Error parsing min ID');
console.log(sorted);
}
}
exports.setMinID = setMinID;