Saturday, April 4, 2009

Salon Letter Filter Script

[WARNING: This script can no longer be used due to changes in Salon's Letter format. The new script is here.]
[On 11/10/09 Salon again changed the format of their letter pages. A new script to filter Salon letters is again available here. The old code is left here in case Salon changes the format back again.]
For those who have been unable to install the Salon Letter Filter Greasemonkey script from the link to the file, here is the text of the script. To install, copy everything between //BEGIN CODE and //END CODE into a text file (do not copy //BEGIN CODE and //END CODE). Name the text file salonletterfilter.user.js and save it. Open the file in your browser (you can drag and drop). If Greasemonkey is installed and active, when you open the file a Greasemonkey dialog will appear asking if you want to install the script. Click on install.

IMPORTANT: Your file name must end with .user.js for Greasemonkey to recognize it as a user script.

Do not panic if it appears that the lines of code end in midair on the blog page. It is all there even if it doesn't display because of the Blogger page layout. Simply select the code, copy it, and paste it into a new text file. Notepad or some other fairly simple text editor is recommended for this.
// To configure the letters filter, you must have a "killfile" variable configured.
// A template for this variable is given below. The "killfile" varable includes a
// comma-delimited string of the nyms of the authors that you wish to filter out.
// A sample "killfile variable configuration looks like:
// new String(killfile = 'author1,author2,author3');
// or
// new String(killfile = 'author');
// Simply replace the word "authors" in the template below with the nyms of the authors you
// wish to expunge, each one separated by a comma, and save the file.
// Entries are case insensitive. Since the "killfile" will become a regular expression,
// regular expression metacharacters (such as "." or "+") appearing in a nym should be
// preceded by a backslash ("\"; e.g., 'L\.W\.M\.') in order to work properly.
new String(killfile = 'authors');
if (killfile.length == 0) exit;
// --------------------------------------------------------------------
// This is a Greasemonkey user script.
// To install, you need Greasemonkey:
// 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 "Letter_Filter", and click Uninstall.
// --------------------------------------------------------------------
// ==UserScript==
// @name Salon Letter filter
// @author Frankly, my dear, ...
// @namespace
// @description Filter letters from Salon. WARNING: manual configuration required. Before use you must edit the script and enter your "killfile" in the string variable near the top of the script.
// @include*
// @version 0.0.1
// ==/UserScript==

// Set debug to 1 to see debug output in Javascript console
var debug = 1;

// Only print information to console if debug is on
function myGM_log(args) {
if (debug == 1) {

// Shortcut function to evalute an XPath in the document
function xpath(query, sourceDoc) {
return document.evaluate(query, sourceDoc, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);

myregexp = new RegExp(killfile.replace(/, */g, "|"), "i");
var allLets, thisLet, allAuthors, thisAuthor, allFooters, thisFooter;
allLets = xpath("//li[@class='letter_node']",document);
allAuthors = xpath("//div[@class='letter_entry_author'] | //div[@class='letter_entry_author premium']",document);
allFooters = xpath("//div[@class='letter_entry_footer']",document);
for (var i = 0; i < allLets.snapshotLength; i++) {
thisLet = allLets.snapshotItem(i);
thisAuthor = allAuthors.snapshotItem(i);
thisFooter = allFooters.snapshotItem(i);
var author = thisAuthor.innerHTML;
if (myregexp.test(author)) {
mymatch = myregexp.exec(author);
thisLet.innerHTML = "<h3><b>Letter from " + mymatch + " deleted</h3></b>" + thisFooter.innerHTML +"<hr>";
//thisLet.innerHTML = "";


mikeinportc said...

...but this is the kind of simple programming task....

If you say so . :) I'll just scroll past the annoying ones . Thanks anyway.

mike said...

It appears they might have broken it again--although I've made no recent changes, the script now only seems to catch about 50% of the blocked-author's letters.

Terry5136 said...

Odd, there are only two comments here! I wonder which limbo is consuming my posts, since they get saved and emailed to me.

Never mind, here's a third attempt after two failures:


Ok, here's the message that I wrote between your April 14, 1:58 PM and your April 14, 3:19 PM postings. It's a bit O/C to post these now, but I'm curious to see if I can make them stick. This one especially, with retrospect, has some utterly useless wild guesses in it:

No, I wasn't thinking of the Greasemonkey script when I mentioned location. Perhaps the site itself has some location setting, or the NSA, or the international channel across to the USA, or who knows? It just occurred to me that there was some extremely rare confluence of events that caused that to happen for me - just once, with one author, on two pages. The script also stopped running for those pages, as did my adblock - all the Salon ads AND commercial ads showed up also. ONLY those two pages.

I'm only whistling in the dark. I don't think anything else has changed at my end. When I started using Chrome, I fairly quickly figured out how to integrate the script and it's been working flawlessly ever since - except once. But don't get me wrong - I'm not necessarily putting it down to the script, especially at this stage, given your own test. I suspect it's some unlikely combination between the script and my computer, or the posts, or Salon, or god knows whom else.

I haven't a clue and the whole problem is way, way beyond my technical knowhow, which is about kindergarten level. But something strange went on and who knows what I stumbled across.

Just the other day I discovered by accident the kind of Shenanigans is up to with their customers - the kind of thing that 999 out of 1,000 customers are never going to notice. There are odd things going on around the internet and without getting paranoid about it, who knows who is up to what?
[end quote]

Hmmm. I see I can't use the html tag "blockquote". Anyway, this next one, also superfluous at this stage, was posted initially between your 3:19 PM post on the same day and my own 3:50 PM post on that day. This one had some information in it that might have helped you, especially since I kept forgetting that you hadn't read it:

I'm impressed with the detective work! Well done.

If you recall, I said I have always used the first script, which you had updated in your third most recent blog entry, and then I modified it according to taste based on your second most recent blog entry. I never revisited it after you posted 'The Whole Enchilada'.

Thus, my remaining lines are:

new String(killfile = 'authors');
if (killfile.length == 0) exit;

As you can see, in my case, 'authors' is the only entry in the killfile.

I haven't changed it yet because I'm not sure if the exit refers to the killfile only or to the entire script. Thus, I wonder if I should 1) simply remove authors and leave the two apostrophes (single quotes); or 2) simply comment out the two lines; or 3) something else.

So now I know I can short circuit the script on a slow loading page by cancelling the loading. But we, or I, that is, am still left with a minor mystery - when those pages load, the post entry is blocked out by the script, but also the script stops running entirely and the salon ads plus the original column width is restored - or rather, left untouched.

Perhaps the reason for this will be obvious to you.

Anyway, again, well spotted! I figured you'd get it because I didn't think you'd leave it alone until you solved it. :)
[end quote]