Source for "Reddit Content Filter"

By pabs
Has 3 other scripts.


// ==UserScript==
// @name           Reddit Content Filter
// @description    Permanently hide unwanted links by user, title, or site.
// @include        http://reddit.com/*
// @include        http://*.reddit.com/*
// @exclude        http://reddit.com/user/*
// @exclude        http://*.reddit.com/user/*
// @exclude        http://reddit.com/info/*
// @exclude        http://*.reddit.com/info/*
// ==/UserScript==

// my defaults:
// sites: madanddangerous.co.uk
// users: dons, martinbishop, PaoloC
// titles: erlang, ocaml, haskell, twitter, emacs, monad, tuple, eclipse, smalltalk, common lisp, clos, r6rs
(function() {
  var version = '0.4';

  /* 
   * load_config: load filters from config.
   */
  load_config = function() {
    var v;

    // load key from config
    get_key = function(key) {
      var v = GM_getValue(key);
      return v ? v.split(/\s*,\s*/) : [];
    }

    // deserialize config and return as hash
    return {
      users: get_key('users'),
      titles: get_key('titles'),
      sites: get_key('sites')
    }
  }

  /* 
   * get_regexps: build list of filter regexps.
   */
  get_regexps = function(cfg) {
    var i, re, re_opt = 'i', 
        ret = { href: [], title: [] };

    // add user matches
    for (i = 0; i < cfg.users.length; i++) {
      re = new RegExp('user\\/' + cfg.users[i], re_opt);
      ret.href.push(re);
    }

    // add site matches
    for (i = 0; i < cfg.sites.length; i++) {
      re = new RegExp(cfg.sites[i], re_opt);
      ret.href.push(re);
    }

    // add title matches
    for (i = 0; i < cfg.titles.length; i++) {
      re = new RegExp(cfg.titles[i], re_opt);
      ret.title.push(re);
    }

    return ret;
  }

  /* 
   * filter_site: hide reddit elements that match filters.
   * 
   * (note: chunks of this function were shamelessly borrowed from the
   * reddit block xkcd script)
   */
  filter_site = function(cfg) {
    var tbl = document.getElementById('siteTable');
    if (!tbl) {
      GM_log("Couldn't find siteTable");
      return 0;
    }

    var trs = tbl.getElementsByTagName('div'),
        tr_group = [];
        hide = false, 
        num_matches = 0,
        res = get_regexps(cfg);

    var hide_entry = function(type, str) {
      GM_log(type + ' match: ' + str);
      hide = true;
      num_matches++;
    }

    // alert('DEBUG: got here');
    for (var i = 0; i < trs.length; i++) {
      var tr = trs[i];

      if (/^pre_/.test(tr.id)) {
        if (hide)
          for (var j = 0; j < tr_group.length; j++)
            tr_group[j].style.display = 'none';

        hide = false;
        tr_group = [];
      }

      var ary = tr.getElementsByTagName('a');
      for (var j = 0; j < ary.length; j++) {
        var a = ary[j], 
            attr = a.attributes;

        // title match
        if (a.className.match(/^title/)) {
          // alert('DEBUG: matched blimey');
          for (var k = 0; !hide && k < res.title.length; k++) {
            var txt = a.textContent;
            if (txt && txt.match(res.title[k]))
              hide_entry('title', res.title[k]);
          }
        }

        // href match
        for (var k = 0; !hide && k < res.href.length; k++)
          if (a.href.match(res.href[k]))
            hide_entry('href', res.href[k]);
      }

      tr_group.push(tr);
    }
    // alert('DEBUG: got here2');

    if (hide)
      for (var j = 0; j < tr_group.length; j++)
        tr_group[j].style.display = 'none';

    return num_matches;
  }

  /*
   * report_matches: add the number of matches to a blurb at the bottom
   * of the page
   */
  report_matches = function(num) {
    var tbl = document.getElementById('siteTable'),
        div = document.createElement('div'),
        msg = 'Removed ' + num + ' stories';

    GM_log(msg);
    if (!tbl)
      return;

    div.innerHTML = '<p><i>' + msg + ' (Reddit Content Filter).</i></p>';
    tbl.parentNode.insertBefore(div, tbl.nextSibling);
  }

  /* 
   * gen_cb: generate menu callback for given entry key.
   */
  gen_cb = function(key) {
    return eval("function() {\n" +
      "var val = GM_getValue('" + key + "s');\n" +
      "if (!val)\n" +
      "  val = '';\n" +

      "val = window.prompt('Edit blocked " + key + " list:', val);\n" +
      "if (val != null) {\n" +
      "  GM_setValue('" + key + "s', val);\n" +
      "}\n" +
    "}\n");
  }

  /* 
   * init_menu: initialize menu entries.
   */
  init_menu = function() {
    GM_registerMenuCommand('Edit Blocked Users...', gen_cb('user'));
    GM_registerMenuCommand('Edit Blocked Sites...', gen_cb('site'));
    GM_registerMenuCommand('Edit Blocked Titles...', gen_cb('title'));
  }

  /* 
   * init: set up reddit content blocker
   */
  init = function() {
    var cfg = load_config(), 
        matches;

    GM_log('Version ' + version + ' started. config = ' + cfg.toSource());

    init_menu();
    matches = filter_site(cfg);
    report_matches(matches);
  }

  // run everything
  init();
})();