Saturday, November 26, 2005

Diving into Greasemonkey, or Roll Your Own Bozofilter

I read about greasemonkey in Wired, and it sounded pretty cool. What it is is a plugin for the Mozilla browser (which is vastly superior to Internet Explorer, kind of like a 2005 Toyota Camry is better than a 1973 Pinto), and what it does is allow you to write javascript snippets that enable you to change the structure of websites you visit in whatever manner you wish (common mods include adding in links to other sites, stripping out ads, or changing ugly color schemes).

This has ramifications for Web advertising and 'brand purity' that probably nobody cares about at this time, because it's only geeks who want to fuck around with writing their own Javascript and CSS and figuring out what XPath expressions are and why you'd want to use them who will be using it. There ARE plenty of pre-written scripts out there, however.

At this point the cautious will rightfully ask whether it's a good idea to install code that hasn't been vetted on your machine, and they'd be right to do so. After all, with companies like Sony trying to get all '1337' on our asses and putting rootkit software on My Morning Jacket CD's so they can 'own' our 'boxen', we really can't be too careful. There was in fact as Security Advisory involving Greasemonkey in July of 2005, discovered by Mark Pilgrim, who we'll talk about more soon. It has since been addressed.

Let's get back on topic. All you really need to do to get started is install Mozilla, and if you do plan to be writing any scripts, you need to choose the Custom Install w/ the developer extensions. You then install the greasemonkey plugin.

There are numerous sites discussing Greasemonkey. The one I ended up bookmarking and going back to was the unappealingly titled 'Dive Into Greasemonkey' by 'Dive Into' Mark Pilgrim (you have to admit, though, having a 'Dive Into' book on the shelf is infinitely better than something from the 'For Dummies' series). Mark's guide is thorough and, here's the really great part: concise. As in brief. As in not full of a lot of useless fluff (you will soon see a 900 page book with a Red Cover and pictures of several nerds on the cover from Wrox publishing if Greasemonkey catches on, though).

Anyhow, for a simple Greasemonkey experiment, I wondered how easy would it be to write a bozo-filter for my favorite running forum, coolrunning.com. It was pretty easy. I am sure there are a million other ways to do it, anyhow here is one (standard disclaimers about for entertainment purposes only, no guarantee of blah blah blah, don't come crying to me if this causes your machine to melt through the floor, etc, apply):

// This is a Greasemonkey user script.
//
// To install, you need Greasemonkey:
// http://greasemonkey.mozdev.org/
// Then restart Firefox and revisit this script.
// Under Tools, there will be a new menu item to
// "Install User Script".
// Accept the default configuration and install.
//
// To uninstall, go to Tools/Manage User Scripts,
// select "CoolerRunning", and click Uninstall.
//
// -------------------------------------------------
//
// ==UserScript==
// @name CoolerRunning
// @namespace SDC
// @description remove wack fuckas
// @include http://www.coolrunning.com/*
// @exclude
// @exclude
// ==/UserScript==

// give us a quickie list of miscreants
// (replace with real usernames before using)
var jerkoffs = new Array("attention ho",
"subliterate cretin",
"troll");

// alt approach: use XPath expression
// note - this is it, zeroes in on 3rd cols
// (user on thread list)
// on comment list it's 1st col.
var xpathMatch;

var allEle = document.evaluate("//TABLE/TBODY/TR/TD/H2",
document,
null,
XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,
null);

GM_log("Got " + allEle.snapshotLength + " with the H2 in TD.");
GM_log(allEle.snapshotItem(0).innerHTML);

if (allEle.snapshotLength > 0 &&
(allEle.snapshotItem(0).innerHTML.indexOf("Clubhouse")>=0)) {
xpathMatch = "//TABLE[@width]/TBODY/TR/TD[3]"; // topics
GM_log("Using topics match");
} else {
xpathMatch = "//TABLE[@width]/TBODY/TR/TD[1]/FONT";
// subject page
GM_log("Using Listing match");
}

allEle = document.evaluate(
xpathMatch,
document,
null,
XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,
null);

GM_log("XPath got:" + allEle.snapshotLength + " items.");

wipeJerky(allEle);

function wipeJerky(theElements) {
var thisEle;
var whereIndex;
var jerkoff;
for (var idex = 0; idex < theElements.snapshotLength;
idex++) {
thisEle = allEle.snapshotItem(idex);
GM_log("Inside: >" + thisEle.innerHTML + "<");
for (var jdex = 0; jdex < jerkoffs.length; jdex++) {
jerkoff = jerkoffs[jdex];
whereIndex = thisEle.innerHTML.indexOf(jerkoff);
if ( whereIndex >= 0) {
GM_log('Looks like ' + jerkoff + ' is here.');
GM_log(' at index:' + whereIndex + ' in the contained html.');
container = thisEle.parentNode;
// may have to back up.
if (!(container.nodeName.toUpperCase() == 'TR')) {
container = container.parentNode;
}
container.parentNode.removeChild(container);
GM_log('Removed ' + jerkoff + '.');
} // found a-hole
} // jerks
} // elements
}

No comments: