Skip to content

Instantly share code, notes, and snippets.

@fergusean
Created May 16, 2015 03:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fergusean/5cce6edd9f81454611fc to your computer and use it in GitHub Desktop.
Save fergusean/5cce6edd9f81454611fc to your computer and use it in GitHub Desktop.
var Image = require('parse-image');
var Comic = Parse.Object.extend('Comic');
Parse.Cloud.job('updateCache', function(request, response) {
getLatestStoredNum(function(num) {
console.log('Latest stored comic is ' + num);
checkForAndCacheNewComicsSince(num, function(success) {
if (success)
response.success('OK');
else
response.error('failed to fetch & cache');
});
})
});
function getLatestStoredNum(callback) {
var query = new Parse.Query(Comic);
query.select('num');
query.descending('num');
query.limit(1);
query.find().then(function(result) {
callback(result.length ? result[0].get('num') : null);
});
}
function checkForAndCacheNewComicsSince(sinceNum, callback) {
// if we didn't get a number, we don't have any we should cache all since 0
sinceNum || (sinceNum = 0);
// fetch the latest comic
fetchComic(null, function(comic) {
// if we didn't get a comic, bail out
if (!comic) return callback(false);
// if this comic number is the same as our "since number",
// there are no updates and we have succeeded at... something
if (comic.get('num') == sinceNum) {
console.log('No updates');
return callback(true);
}
// debug!
console.log('Latest comic is ' + comic.get('num'));
// ok, fine, we need to fetch and cache all comics since the last one we have
// oh and by the way, here's the latest one
fetchAndCacheComicsSinceWithLatestComic(sinceNum, callback, comic);
});
}
function fetchAndCacheComicsSinceWithLatestComic(sinceNum, callback, latestComic) {
// set our current number as 1 above the "since" number
var currentNum = sinceNum + 1;
// attach image dimensions to the latest
attachDimensions(latestComic, function(success) {
// fail?
if (!success) return callback(false);
// save our latest
persistComic(latestComic, function(success) {
// fail?
if (!success) return callback(false);
// begin downloading the rest
__downloadNext();
});
});
// callback
function __downloadNext() {
// if the current number is equal to the latest comic's number, we're done!
if (currentNum == latestComic.get('num')) return callback(true);
// fetch the comic
fetchComic(currentNum, function(comic) {
// if we didn't get a comic, failure :(
if (!comic) return callback(false);
// attach the image dimensions
attachDimensions(comic, function(success) {
// fail?
if (!success) return callback(false);
// save it
persistComic(comic, function(success) {
// fail?
if (!success) return callback(false);
// increment our current number
currentNum++;
// if the number is 404, skip it, because Randall's a funny bitch
if (currentNum == 404) currentNum++;
// proceed to the next
__downloadNext();
});
});
});
}
}
function fetchComic(id, callback) {
var url = 'http://xkcd.com/';
id && (url += id + '/');
url += 'info.0.json';
Parse.Cloud.httpRequest({
url: url
}).then(function(httpResponse) {
if (!httpResponse.data || !httpResponse.data.num) {
console.error('Unexpected response from URL ' + url);
callback(false);
}
else {
console.log('Fetched comic ' + httpResponse.data.num);
var comic = new Comic;
for (key in httpResponse.data)
comic.set(key, httpResponse.data[key]);
callback(comic);
}
}, function(httpResponse) {
console.error('Request failed with response code ' + httpResponse.status + ' to URL ' + url);
callback(false);
});
}
function attachDimensions(comic, callback) {
Parse.Cloud.httpRequest({
url: comic.get('img'),
success: function(response) {
console.log('Retrieved image for comic ' + comic.get('num'));
var image = new Image();
image.setData(response.buffer, {
success: function() {
comic.set('img_w', image.width());
comic.set('img_h', image.height());
callback(true);
},
error: function(error) {
console.error('Failed to load image for comic ' + comic.get('num') + ': ' + error.code);
callback(false);
}
});
},
error: function(error) {
console.error('Failed to receive image for comic ' + comic.get('num') + ' from URL ' + comic.get('img') + ': ' + error.code);
callback(false);
}
});
}
function persistComic(comic, callback) {
comic.save(null, {
success: function() {
console.log('Stored comic ' + comic.get('num'));
callback(true);
},
error: function(error) {
console.log('Failed to store comic ' + comic.get('num') + ': ' + error.code);
callback(false);
}
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment