djekl
9/5/2012 - 2:36 PM

PhantomJS - Xbox Achievement JSON (for your latest game)

PhantomJS - Xbox Achievement JSON (for your latest game)

/*
This script provides a quick and dirty way of getting your most recent game achievement json data.

This is a lightly modified version of Jabbslad's script found here: https://gist.github.com/1653745

James Coverdale - imjam.es 2012

*/

var fs = require('fs'),
    system = require('system');
	
var name = "";

if (phantom.args.length !== 2) {
    //console.log('Usage xbox.js <username> <password>');
    phantom.exit();
}

var page = new WebPage({
    'page.settings.loadImages': false
});

/*
* Callback to process page when finshed loading
*/
page.onLoadFinished = function(status) {
    if (status !== "success") {
       console.log("Unable to access network");
    } else {
        var url = getPageUrl();
		
        switch (true) {
        case /login.srf/.test(url):
            // Step 1 - Login			
            page.evaluate(fillFormFunctionAsString());
            break;
        case /post.srf/.test(url):
            // Step 2 - Process Cookies			
            break;
	case /Details/.test(url):
	    // We got the achievements
            parseGame();
            phantom.exit();
            break;
        case /Activity$/.test(url):
            // We did it!			
            parseActivity();            
            break;
        default:
            // uh oh we hit an unexpected url
            phantom.exit(1);
        }
    }
}

function getPageUrl() {
    return page.evaluate(function() {
        return location.href
    });
}

//This whole function will need reworking ideally, must be a better way of grabbing the json
//but this works for now
function parseGame() {

	var index = page.content.indexOf("broker.publish(routes.activity.details.load, ") + 45; 
	var lastindex = page.content.indexOf("</script>", index); 
	
	var json = page.content.substring(index, lastindex);
	json = json.split("});").join("");
	json = json + "}";

	// You could just push the json to the console to allow use in the command line, i.e. pipe it to another script.
	f = null;
	f = fs.open(name + '.json', "w");
	f.write(json);
	f.close();          

}

function parseActivity() {
	
   try {       
   
	   var contents = page.content;   
	   
	   // Again this string manip is not ideal, too much that could go wrong if the site changes
	   var index = contents.indexOf("<a href=\"/en-US/Activity/Details?titleId=") + 41; 
	   var url = contents.substring(index, contents.indexOf("\"", index));    
	   var nameindex = contents.indexOf("alt=\"", index) + 5;   
	   name = contents.substring(nameindex, contents.indexOf("\"", nameindex));
	   
	   // make the game name lower case and remove any spaces
	   name = name.toLowerCase().split(" ").join(""); 
		
	   // Load the latest game page
	   page.open(encodeURI('https://live.xbox.com/en-US/Activity/Details?titleId=' + url));		
    } 
    catch (e) {
       console.log(e);
    }
}

/*
* Hack due to phantomjs page.evaluate limitations:- 
* http://code.google.com/p/phantomjs/issues/detail?id=132
*/
function fillFormFunctionAsString() {
    return "function() {" 
         + "var form = document.querySelector(\"form[name='f1']\"); " 
         + "var login = form.querySelector(\"input[name='login']\"); " 
         + "login.value = '" + phantom.args[0] + "'; " 
         + "var passwd = form.querySelector(\"input[name='passwd']\"); " 
         + "passwd.value = '" + phantom.args[1] + "'; " 
         + "var kmsi = form.querySelector(\"input[name='KMSI']\"); " 
         + "kmsi.value = '2'; " 
         + "form.querySelector('#idSIButton9').click();}";
};

page.open(encodeURI('https://live.xbox.com/en-US/Activity'));