Monday, July 7, 2008

Netflix Queue Randomizer

Security is where I spend the bulk of my time, however I have dabbled quite extensively in other areas. So it is no surprise when every once in a while I do something that is not security related. This is one of those times.

Netflix. Love it or hate it, but me not having a TV makes Netflix a lifesaver because I can get my dose of movies while multitasking (current movie: Golden Child). The problem I continually find is that my queue directly follows my particular mood I was in when I was adding to the queue. The result is that the movies in my queue will have this flow to them that is not always appealing. For example, I watched a string of westerns last week, however that was because a week or two prior I watched Tombstone and then went and selected movies that Netflix said I'd like based on my 4-star rating of Tombstone.

Several months I ago I wrote to Netflix asking them for the ability to randomize my queue. Sure, I can do this by hand, however when I have 50 movies in my queue it gets old after the first time you do it. Since I figured this would be useful to others, it would not be unreasonable to ask Netflix to implement this. Furthermore, the queue manipulation stuff is already there and used by the queue manager, so it makes me wonder why it was never implemented. Understandably, they probably have other things on their plate. An API, perhaps?

The result is the following Greasemonkey abomination:

// ==UserScript==
// @name           Netflix Queue Randomizer
// @namespace      http://www.netflix.com/Queue
// @include        http://www.netflix.com/Queue
// ==/UserScript==

function moveToTop(id, from) {
 GM_xmlhttpRequest({
   method: 'GET',
   url: 'http://www.netflix.com/QueueReorder?movieid=' + id + '&from=' + from + '&pos=1&sz=0&mt=true&ftype=DD',
   headers: { 'X-Requested-With': 'XMLHttpRequest' }
 });
}

function randomSort() {
 return (Math.round(Math.random()) - 0.5);
}

function randomizeQueue() {
 var inputs = document.getElementsByTagName('input');
 var idRe = /^OP(\d{8})$/;
 var curIds = new Array();
 var curPoss = new Array();
 var newOrder = new Array();


// find all of the movies in the queue and store their ID and current
  // position in the queue
  for (var i=0; i < inputs.length; i++) {
    if (inputs[i].type == 'hidden' && inputs[i].name.match(idRe)) {
      var matches = idRe.exec(inputs[i].name);
      curIds.push(matches[1]);
      curPoss.push(inputs[i].value);
    }
  }

  // create a new array that is the same size as the movie queue and
  // randomize it.  This has to be done this was because QueueReorder does
  // not support moving to arbitrary positions, only the top.
  for (var i=0; i < curIds.length; i++) {
    newOrder[i] = i;
  }
  newOrder.sort(randomSort);

  // now map the current movies and their positions to their new homes
  for (var i=0; i < newOrder.length; i++) {
    moveToTop(curIds[newOrder[i]], curPoss[newOrder[i]])
  }

  window.location.reload();
}

// Create a new div that contains the 'Randomize Queue' link, and then prove
// that I have nearly zero HTML foo by being unable to place the link to the
// left of the bottom 'Update DVD Queue' button
var qFooter = document.getElementById('updateQueue2');
var rDiv = document.createElement('div');
rDiv.setAttribute('class', 'd1_qt');

var rLink = document.createElement('a');
rLink.addEventListener('click', randomizeQueue, false);

var rText = document.createTextNode("Randomize Queue");
rLink.appendChild(rText);
rDiv.appendChild(rLink);

qFooter.parentNode.insertBefore(rDiv, qFooter);


Obviously for any of this to work you'll need to have Greasemonkey installed, which requires Firefox, an understanding of how to load this (Tools -> Greasemonkey -> New User Script), and a Netflix account.

Enjoy?

2 comments:

Anonymous said...

Couldn't get it to work. Asks for a "Namespace"

Anonymous said...

why go to all that trouble I use http://www.random.org/ My que has 465 I select movie between 1 - 465 I move that one to top. I select movie 1 -464 I move that one t the top thats it.