Skip to content

Instantly share code, notes, and snippets.

@mshock
Created October 29, 2015 02:39
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 mshock/425f22dbbf141b1c35aa to your computer and use it in GitHub Desktop.
Save mshock/425f22dbbf141b1c35aa to your computer and use it in GitHub Desktop.
k3kc stock monitor - Google Apps Script
var max_errors = 5;
var EMAIL = Session.getActiveUser().getEmail();
var scriptProperties = PropertiesService.getScriptProperties();
//scriptProperties.deleteAllProperties();
function myFunction() {
var current_stock = {};
var shop_url = 'http://www.k3kc.com/shop/';
var links = new Array();
var html = getXMLRequest(shop_url);
// determine number of shop pages to fetch and parse
var page_nums = getElementsByTagName(getElementsByClassName(html, 'page-numbers')[0], 'li').length;
for (var p = 1; p <= page_nums; p++) {
html = getXMLRequest(shop_url + 'page/' + p);
// parse a page for product links
var product_links = getElementsByTagName(html, 'table');
for (i in product_links) {
links.push(getElementsByTagName(product_links[i], 'a')[0].getAttribute('href').getValue());
}
}
// check stock for each link
var name_re = new RegExp(/shop\/(.+)\/$/);
var stock_re = new RegExp(/Only (\d+)/);
for (var j = 0; j < links.length; j++) {
var name = name_re.exec(links[j])[1];
var html = getHTMLRequest(links[j]);
if (!html) {
Logger.log('FAILED: ' + links[j]);
continue;
}
if (html.match('in-stock')) {
var stock = stock_re.exec(html);
if (stock){
// Logger.log(links[j] + ' ' + stock[1]);
current_stock[name] = stock[1];
}
else {
// Logger.log(links[j] + " In stock");
current_stock[name] = "in stock";
}
}
else {
// Logger.log(links[j] + " Out of stock");
current_stock[name] = "out of stock";
}
}
Logger.log(current_stock);
var num_changed = 0;
var body = '';
for (var key in current_stock) {
var curr = current_stock[key];
var prev = scriptProperties[key];
if (curr != prev) {
Logger.log(key + ' changed from: ' + prev + ' to: ' + curr);
body += key + ' changed from: ' + prev + ' to: ' + curr + "\n";
scriptProperties.setProperty(key, curr);
}
}
if (num_changed > 0) {
var title = num_changed + ' updated items';
MailApp.sendEmail(EMAIL, title, body, {name: 'K3 Stock'});
Logger.log('email sent');
}
else {
Logger.log('no changes detected');
}
}
function getHTMLRequest(url) {
var errors = 0;
Utilities.sleep(1000);
var page;
try {
page = UrlFetchApp.fetch(url).getContentText();
}
catch (e) {
if (errors++ > max_errors) {
Logger.log("could not fetch HTML URL: " + url);
throw Error("too many attempts: " + url);
}
Utilities.sleep(5000);
}
return page;
}
function getXMLRequest(url) {
var errors = 0;
Utilities.sleep(1000);
var page;
try {
page = UrlFetchApp.fetch(url);
}
catch (e) {
if (errors++ > max_errors) {
Logger.log("could not fetch XML URL: " + url);
throw Error("too many attempts: " + url);
}
Utilities.sleep(5000);
}
var doc = Xml.parse(page, true);
var bodyHtml = doc.html.body.toXmlString();
doc = XmlService.parse(bodyHtml);
var html = doc.getRootElement();
return html;
}
function getElementsByClassName(element, classToFind) {
var data = [];
var descendants = element.getDescendants();
descendants.push(element);
for(i in descendants) {
var elt = descendants[i].asElement();
if(elt != null) {
var classes = elt.getAttribute('class');
if(classes != null) {
classes = classes.getValue();
if(classes == classToFind) data.push(elt);
else {
classes = classes.split(' ');
for(j in classes) {
if(classes[j] == classToFind) {
data.push(elt);
break;
}
}
}
}
}
}
return data;
}
function getElementsByTagName(element, tagName) {
var data = [];
var descendants = element.getDescendants();
for(i in descendants) {
var elt = descendants[i].asElement();
if( elt !=null && elt.getName()== tagName) data.push(elt);
}
return data;
}
function getElementById(element, idToFind) {
var descendants = element.getDescendants();
for(i in descendants) {
var elt = descendants[i].asElement();
if( elt !=null) {
var id = elt.getAttribute('id');
if( id !=null && id.getValue()== idToFind) return elt;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment