RaaW

Reddit as a Weapon script. Parts and idea by /u/noeatnosleep, enhanced by /u/enim, /u/creesch, /u/skeeto, and /u/djimbob. RaaW adds links for page-wide voting and reporting. It adds a 'report to /r/spam' link, an 'analyze user submission domains' link, and a 'report to /r/botwatchman' link to userpages. RaaW disables the np. domain. RaaW Adds a 'show source' button for comments. DISCLIAMER: Use this at your own risk. If the report button is misued, you could be shadowbanned.

当前为 2014-10-09 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name RaaW
// @version 3.1.1
// @namespace RaaW
// @description Reddit as a Weapon script. Parts and idea by /u/noeatnosleep, enhanced by /u/enim, /u/creesch, /u/skeeto, and /u/djimbob. RaaW adds links for page-wide voting and reporting. It adds a 'report to /r/spam' link, an 'analyze user submission domains' link, and a 'report to /r/botwatchman' link to userpages. RaaW disables the np. domain. RaaW Adds a 'show source' button for comments.  DISCLIAMER: Use this at your own risk. If the report button is misued, you could be shadowbanned.
// @include http://www.reddit.com/user/*
// @include http://www.reddit.com/r/*
// @include http://*reddit.com/*
// @include https://www.reddit.com/user/*
// @include https://www.reddit.com/r/*
// @include https://*reddit.com/*
// @require https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js
// ==/UserScript==

this.jQuery = this.jQuery = jQuery.noConflict(true);

// define a basic object that we can extend with our functions so we do not accidentally
// override other stuff
var RaaW = {
    // ////////////////////////////////////////////////////////////////////////
    // constants
    // ////////////////////////////////////////////////////////////////////////

    // some css properties for the links in the toolbox
    LINK_CSS: {
        'color': '#000',
    },

    // ////////////////////////////////////////////////////////////////////////
    // instance variables
    // ////////////////////////////////////////////////////////////////////////

    raawToolbar: false,

    // true if we are moderator on the current page (by checking if .moderator is present)
    // in <body class="...">
    isModerator: false,

    currentPage: 'user',

    modHash: false,

    // ////////////////////////////////////////////////////////////////////////
    // various helper functions
    // ////////////////////////////////////////////////////////////////////////

    /**
     * Function grabs the username of the current viewed profile.
     *
     * Returns:
     *  (string) username or undefined if not found
     */
    _getUsername: function() {
      return jQuery(document).find('.pagename.selected').text();
    },

    // ////////////////////////////////////////////////////////////////////////
    // initialization
    // ////////////////////////////////////////////////////////////////////////

    /**
    * Initialize RaaW. Will fetch some values like current page and after
    * that initialize the toolbar.
    */
    init: function() {
        // first gather all the information needed
        this._loadEnvironment();

        // now add some elements we will need
        this._injectElements();

        // add the toolbar
        this._generateToolbar();

        // after we created everything connect it
        this._registerListener();
    },

    /**
     * Load environment values like current page.
     */
    _loadEnvironment: function() {
        // set current page
        this.currentPage = document.URL.split('reddit.com')[1].split('/')[1];

        // check if we are moderator
        this.isModerator = jQuery('body').hasClass('moderator');
    },

    /**
     * Adds/modifies needed elements to the reddit page (e.g. 'toggle source' links).
     */
    _injectElements: function() {
        // add links 'toogle source' to comments
        var toggleSourceCodeEl = jQuery('<li><a class="raawToggleSourceCode" href="#">view source</a></li>');
        jQuery('.entry .flat-list').append(toggleSourceCodeEl);

        //disable .np
        if (document.documentElement.lang === 'np') {
            document.documentElement.lang = 'en-us';
        }

        // add subscriber class to body tag
        jQuery('body').addClass('subscriber');

        // replace links on the page
        Array.forEach( document.links, function(a) {
            a.href = a.href.replace( "https://i.imgur.com", "http://imgur.com");
            a.href = a.href.replace( "https://imgur.com", "http://imgur.com");
        });

        // set checkbox 'limit my search to /r/...' checked
        jQuery('form#search input[name="restrict_sr"]').prop('checked', true);

        // add 'save as mod' button
        if(this.isModerator === true) {
          this._injectSaveAsMod();
        }
    },

    /**
     * Register all click listener for the RaaW toolbar links. We do not distingish if we
     * are on /user or something else. There should be no noticeable impact on performance
     * and we save some maintenance effort.
     */
    _registerListener: function() {
        // we don't want js to bind 'this' to the global object. therefore we use a trick.
        // whenever you need a 'this' reference inside one of the functions pointing to
        // the RaaW object use 'that'
        var that = this;

        // register click handler for the user toolbar links
        jQuery('#raawReportComment').click(function(e) {
          that.reportAll(e);
        });
        jQuery('#raawBotwatchmanSend').click(function(e) {
          that.botwatchmanSend(e)
        });
        jQuery('#raawAnalyzeSend').click(function(e) {
          that.analyzeSend(e)
        });
        jQuery('#raawReportUserToSpam').click(function(e) {
          that.reportUserToSpam(e)
        });
        jQuery('#raawAdminSend').click(function(e) {
          that.adminSend(e)
        });

        // register handler for the other toolbar links
        jQuery('#raawDownvoteComment').click(function(e) {
          that.downvoteAll(e)
        });
        jQuery('#raawUpvoteComment').click(function(e) {
          that.upvoteAll(e)
        });
        jQuery('#raawComposeNew').click(function(e) {
          that.composeNew(e)
        });

        //jQuery('.raawToggleSourceCode').click(this.toggleSourceCode);
        jQuery('.raawToggleSourceCode').click(function(e) {
            that.toggleSourceCode(e);
        });
    },

    // ////////////////////////////////////////////////////////////////////////
    // toolbar stuff
    // ////////////////////////////////////////////////////////////////////////

    /**
    * Helper function used to create an a-element.
    *
    * Parameters:
    *  id (string) - id attribute value
    *  href (string) - href attribute value
    *  text (string) - elements text
    *
    * Returns:
    *  jQuery element instance
    */
    _generateToolbarLink: function(id, href, text) {
        var link = jQuery('<a id="' + id + '" href="' + href + '">' + text + '</a>');
        jQuery(link).css(this.LINK_CSS);
        return link;
    },

    /**
     * Generate the toolbar on top of the page.
     */
    _generateToolbar: function() {
        // apply some styles to the header
        jQuery('#header').css({
            'paddingTop': '18px'
        });

        // create the new raaw toolbar and insert into body
        this.raawToolbar = jQuery('<div id="raawToolbar"></div>');
        jQuery('body').prepend(this.raawToolbar);

        // apply style to the new toolbar
        jQuery(this.raawToolbar).css({
            'color': '#000'
            , 'background-color': '#f0f0f0'
            , 'border-bottom': '1px solid #000'
            , 'font-family': 'erdana, arial, helvetica, sans-serif'
            , 'font-size': '90%'
            , 'height': '12px'
            , 'padding': '3px 0px 3px 6px'
            , 'text-transform': 'uppercase'
            , 'width': '100%'
            , 'z-index': '+999999'
            , 'position': 'fixed'
            , 'top': '0'
        });

        // fill toolbar with content depending on parsed page
        var toolbarLinks = new Array();
        if(this.currentPage === 'user') {
            toolbarLinks.push(this._generateToolbarLink('raawReportComment', '#', 'REPORT ALL'));
            toolbarLinks.push(this._generateToolbarLink('raawBotwatchmanSend', '#', ' | /R/BOTWATCHMAN'));
            toolbarLinks.push(this._generateToolbarLink('raawAnalyzeSend', '#', ' | ANALYZE'));
            toolbarLinks.push(this._generateToolbarLink('raawReportUserToSpam', '#', ' | /R/SPAM'));
            toolbarLinks.push(this._generateToolbarLink('raawAdminSend', '#', ' | ADMIN'));
        } else {
            toolbarLinks.push(this._generateToolbarLink('raawDownvoteComment', '#', 'DOWNVOTE ALL'));
            toolbarLinks.push(this._generateToolbarLink('raawUpvoteComment', '#', ' | UPVOTE ALL'));
            toolbarLinks.push(this._generateToolbarLink('raawComposeNew', '#', ' | COMPOSE'));
        }

        for(i = 0; i < toolbarLinks.length; i++) {
            jQuery(this.raawToolbar).append(toolbarLinks[i]);
        }
    },

    // ////////////////////////////////////////////////////////////////////////
    // functions for user toolbar
    // ////////////////////////////////////////////////////////////////////////
    /**
     * Report a given item using the reddit api.
     *
     * Parameters:
     *  fullname (string) - fullname of item to report
     *  modhash (string) - modhash to use for reporting
     */
    _reportItem: function(fullname, modhash) {
        var modhash = reddit.modhash;
        jQuery.post('http://www.reddit.com/api/report', {'id': fullname, 'uh': modHash});
    },

    /**
     * Report all items on the page.
     *
     * Parameters:
     *  click (jQuery click event) - the jQuery click event.
     */
    reportAll: function(click) {
        click.preventDefault();

        var isConfirmed = confirm("This will report all items on the page.");
        if (isConfirmed === true) {
            var that = this;
            var modhash = reddit.modhash;

            // load all fullname of the comments on the page
            jQuery('.commentarea .thing').each(function(index, el) {
                this._reportItem(fullname, modhash);
                fullnames.push(jQuery(el).attr('data-fullname'));
            });

            // not accurate but will do
            alert('All items on this page were reported.');
        } else {
            alert('Report canceled');
        }
    },

    /**
     * Open a new window to submit a user to /r/botwatchman.
     *
     * Parameters:
     *  click (jQuery click event) - the jQuery click event.
     */
    botwatchmanSend: function(click) {
      click.preventDefault();
      var username = this._getUsername();
      window.open('http://www.reddit.com/r/botwatchman/submit?title=overview for ' + username + '&url=http://www.reddit.com/user/' + username);
    },

    /**
     * Send a new message to /u/analyzereddit with subject 'analyze' and a username
     * as message.
     *
     * Parameters:
     *  click (jQuery click event) - the jQuery click event.
     */
    analyzeSend: function(click) {
      click.preventDefault();
      var username = this._getUsername();
      window.open('http://www.reddit.com/message/compose/?to=analyzereddit&subject=analyze&message=' + username);
    },


    /**
     * Open a new window to report a user to /r/spam.
     *
     * Parameters:
     *  click (jQuery click event) - the jQuery click event.
     */
    reportUserToSpam: function(click) {
      click.preventDefault();
      var username = this._getUsername();
      window.open('http://www.reddit.com/r/spam/submit?title=overview for '+ username + '&resubmit=true&url=http://www.reddit.com/user/' + username);
    },

    /**
     * Open a new window to send a new message to /r/reddit.com.
     */
    adminSend: function(click){
      click.preventDefault();
      var username = this._getUsername();
      window.open('http://www.reddit.com/message/compose/?to=/r/reddit.com&message=/u/'+ username);
    },

    // ////////////////////////////////////////////////////////////////////////
    // functions for default toolbar
    // ////////////////////////////////////////////////////////////////////////

    /**
     * Downvote various comments on all kinds of pages.
     *
     * Returns:
     *  (boolean)
     */
    downvoteAll: function(click) {
      click.preventDefault();

      // we are on a user page
      if(this.currentPage === 'user') {
        var items = jQuery('#siteTable').find('.arrow.down');
        Array.prototype.forEach.call(items, function(el, i){
          setTimeout(function() {
            el.click();
          },100 + ( i * 400 ));
        });
        return false;
      } else {
        // all div.comment elements on the page
        var comments = jQuery('.comment');

        // no comments found
        if(comments.length == 0) {
          var items = jQuery('#siteTable').find('.arrow.down');
          Array.prototype.forEach.call(items, function(el, i){
            setTimeout(function(){
              el.click();
            },100 + ( i * 400 ));
          });
          return false;
        } else {
          var items = jQuery('.commentarea').find('.arrow.down');
          Array.prototype.forEach.call(items, function(el, i){
            setTimeout(function(){
              el.click();
            },100 + ( i * 400 ));
          });
          return false;
        }
      }
    },

    /**
     * Upvote various comments on all kinds of pages.
     *
     * Returns:
     *  (boolean)
     */
    upvoteAll: function(click) {
      click.preventDefault();

      // we are on a user page
      if (this.currentPage === 'user'){
        var items = jQuery('#siteTable').find('.arrow.up');
        Array.prototype.forEach.call(items, function(el, i){
          setTimeout(function(){
            el.click();
          },100 + ( i * 400 ));
        });
        return false;
      }
      else {
        // all div.comment elements on the page
        var comments = jQuery('.comment');

        // no comments found
        if (comments.length === 0) {
          var items = jQuery('#siteTable').find('.arrow.up');
          Array.prototype.forEach.call(items, function(el, i){
            setTimeout(function() {
             el.click();
            },100 + ( i * 400 ));
          });
          return false;
        } else {
          var items = jQuery('.commentarea').find('.arrow.up');
          Array.prototype.forEach.call(items, function(el, i){
            setTimeout(function() {
              el.click();
            },100 + ( i * 400 ));
          });
          return false;
        }
      }
    },

    /**
     * Open a new window to compose a new message.
     *
     * Parameters:
     *  click (jQuery click event) - the jQuery click event.
     */
    composeNew: function(click) {
      click.preventDefault();
      window.open('http://www.reddit.com/message/compose/');
    },

    // ////////////////////////////////////////////////////////////////////////
    // 'view source' related functions
    // ////////////////////////////////////////////////////////////////////////

    /**
     * Helper function to fetch the sourcecode of comments/links/messages using the
     * reddit api.
     *
     * Parameters:
     *  url (string) - because of the diversity of the api provide a url with the needed attributes
     *  fullname (string) - fullname needed to search if loading messages
     *  callback (function(source)) - callback function to call when api call is done
     */
    _fetchSourceCode: function(url, fullname, callback) {
        jQuery.getJSON(url).done(function(response) {
            // check what type of posting we're looking at (check api for more information)
            var postingType = response.data.children[0].kind;

            // unfortunately the returned json object has no unified structure so
            // we need a bit more logic here
            var source;
            if(postingType === 't1') { // comment
                source = response.data.children[0].data.body;
            } else if(postingType === 't3') { // link (post); will be empty for videos or similiar
                source = response.data.children[0].data.selftext;
            } else if(postingType === 't4') { // message
                // the current api url loads a message thread so we need to find the
                // desired message
                rawData = response.data.children[0].data;
                if(rawData.name === fullname) {
                  source = rawData.body;
                } else {
                  // search through replies
                  var replies = rawData.replies.data.children;
                  for(var i = 0; i < replies.length; i++) {
                    var replyRaw = replies[i].data;
                    if(replyRaw.name === fullname) {
                      source = replyRaw.body;
                      break;
                    }
                  }
                }
            }

            callback(source);
        });
    },

    /**
     * Create a textarea to display source code
     *
     * Parameters:
     *  source (string) - source code to display
     *  fullname (string) - fullname of link/comment/message so we can later identify if we already loaded the source
     *  prependTo (jQuery element) - element to prepend the textarea to
     */
    _createSourceCodeTextarea: function(source, fullname, prependTo) {
      // create a textarea to display source and add it to the dom
      var textAreaEl = jQuery('<textarea class="'+fullname+'">'+source+'</textarea>');
      jQuery(textAreaEl).css({
          'display': 'block'
          , 'width': '90%'
          , 'height': '100px'
      });

      // insert textarea
      jQuery(prependTo).prepend(textAreaEl);
    },

    /**
     * Toggle source code.
     *
     * Parameters:
     *  click (jQuery click event) - the jQuery click event.
     */
    toggleSourceCode: function(click) {
        click.preventDefault();

        // grab the clicked link element
        var linkEl = jQuery(click.target);

        // get the data-fullname attribute to provide an id to 'throw at the api'
        var dataFullname = jQuery(linkEl).closest('.thing').attr('data-fullname');

        var isTextAreaPresent = jQuery('textarea.'+dataFullname);
        if(isTextAreaPresent.length == 1) {
            jQuery(isTextAreaPresent).toggle();
        } else {
            // figure out the element where we're going to insert the textarea
            var prependTo = jQuery(linkEl).parent().parent();

            // do an ajax request to fetch the data from the api
            // because we cannot fetch a message and a link/comment with the same api call
            // we need to figure out, if we are on a message site
            var apiURL;
            if(this.currentPage === 'message') {
                // cut off t4_ for filtering
                messageId =  dataFullname.slice(3, dataFullname.length);
                apiURL = '/message/messages/.json?mid='+messageId+'&count=1';
            } else {
                apiURL = '/api/info.json?id=' + dataFullname;
            }

            var that = this;
            this._fetchSourceCode(apiURL, dataFullname, function(source) {
                that._createSourceCodeTextarea(source, dataFullname, prependTo);
            });
        }
    },

    // ////////////////////////////////////////////////////////////////////////
    // 'save as mod' related stuff
    // ////////////////////////////////////////////////////////////////////////

    /**
     * Register a new event listener in the given div.
     *
     * Parameters:
     *  div (jQuery element) - div with the class .usertext-buttons
     */
    _updateSavesAsModListener: function(form) {

    },

    /**
     * Place a 'save as mod' in the comment forms.
     *
     * Parameters:
     *  el (jQuery element) - form element to place the button in; leave out to inject into all
     */
    _injectSaveAsMod: function(el) {
      var that = this;
      if(typeof el === 'undefined') {
        el = false;
      }

      // no element given -> inject into all forms
      var injectHere = new Array();
      if(el === false) {
        injectHere = jQuery('.usertext-buttons');
      } else {
        injectHere.push(jQuery(el).find('.usertext-buttons')[0]);
      }

      // inject between save and cancel
      for(i = 0; i < injectHere.length; i++) {
        // element where the buttons life in
        var divEl = injectHere[i];

        // button to inject; register click function...
        var buttonEl = jQuery('<button type="button" class="raawSaveAsMod">save as mod</button>');
        jQuery(buttonEl).click(function(e) {
          that.saveAsMod(e);
        });

        // find save button and add save as mod after that
        jQuery(divEl).find('button[type="submit"]').after(buttonEl);
      }

      // remove the buttons from the edit form
      jQuery('div.entry .usertext-buttons button.raawSaveAsMod').remove();

      // find all  reply links
      var replyButtons = jQuery('ul.flat-list li a').filter(function(index, el) {
        return jQuery(el).text() === 'reply';
      });

      for(i = 0; i < replyButtons.length; i++) {
        var button = replyButtons[i];
        jQuery(button).click(function(e) {
          setTimeout(function() {
            var allButtons = jQuery('button.raawSaveAsMod');
            for(i = 0; i < allButtons.length; i++) {
              var button = allButtons[i];
              jQuery(button).off('click');
              jQuery(button).click(function(e) {
                that.saveAsMod(e);
              });
            }
          }, 500);
        });
      }
    },

    /**
     * Method will prevent a comment form to submit in the first place. Will fetch the
     * thing id to use it for distinguishing. After that will submit the form and when the
     * submit is finished distinguish the comment itself.
     *
     * Parameters:
     *  click (jQuery click event)
     */
    saveAsMod: function(click) {
      click.preventDefault();
      var form = jQuery(click.target).closest('form.usertext');

      // get parent
      var hiddenInput = jQuery(form).children('input[name="thing_id"]')[0];
      var parent = jQuery(hiddenInput).val();

      // get comment text
      var textarea = jQuery(form).find('textarea')[0];
      var commentText = jQuery(textarea).val();

      var modhash = reddit.modhash;
      // post comment
      data = {
        'api_type': 'json'
        , 'text': commentText
        , 'thing_id': parent
        , 'uh': modhash
      };
      jQuery.post('/api/comment', data).done(function(response) {
        if(response.json.errors.length > 0) {
          console.log('Error while posting comment:');
          console.log(response.json.errors);
          alert('Error while posting comment. Please check the console for more information!');
          return;
        }

        // distinguish
        var commentData = response.json.data.things[0].data;
        var data = {
          'id': commentData.id
          , 'api_type': 'json'
          , 'how': 'yes'
          , 'uh': modhash
        };
        jQuery.post('/api/distinguish', data).done(function(response) {
          if(response.json.errors.length > 0) {
            console.log('Error while posting comment:');
            console.log(response.json.errors);
            alert('Error while posting comment. Please check the console for more information!');
            return;
          }

          location.reload();
        });
      });
    },

};

RaaW.Nuke = {
  init: function() {
    if(document.querySelector('body.moderator')) { // only execute if you are a moderator
        var nuke_button = new Array();
        var divels = document.querySelectorAll('div.noncollapsed');
        var comment_ids = new Array();
        var use_image = false;

        // create img DOM element to clone
        if(use_image) {
            try {
                var img_element =  document.createElement('img');
                img_element.setAttribute('alt', 'Nuke!');
                img_element.setAttribute('src', chrome.extension.getURL('nuke.png'));
            } catch(e) {
                use_image = false;
            }
        }
        for (var i = 0; i < divels.length; i++) {
            var author_link = divels[i].querySelector('p.tagline>a.author,p.tagline>span.author,p.tagline>em');
            // p.tagline>a.author is normal comment;
            // some author deleted comments seem to have either
            // p.tagline>span.author or p.tagline>em

            comment_ids[i] = divels[i].getAttribute('data-fullname');
            // console.log(i + ':' + comment_ids);
            if(author_link) {
                // create link DOM element with img inside link
                nuke_button[i] = document.createElement('a')
                nuke_button[i].setAttribute('href', 'javascript:void(0)');
                nuke_button[i].setAttribute('title', 'Nuke!');
                nuke_button[i].setAttribute('id', 'nuke_'+i);
                if(use_image) {
                    nuke_button[i].appendChild(img_element.cloneNode(true));
                } else {
                    nuke_button[i].innerHTML= "[Nuke]";
                }

                // append after the author's name
                author_link.parentNode.insertBefore(nuke_button[i], author_link.nextSibling);

                // Add listener for click; using IIFE to function with _i as value of i when created; not when click
                nuke_button[i].addEventListener('click',
                (function(_i) {
                    return function() {
                        var continue_thread = divels[_i].querySelectorAll('span.morecomments>a');
                        var comment_str = " comments?";
                        if(continue_thread.length > 0) {
                            comment_str = "+ comments (more after expanding collapsed threads; there will be a pause before the first deletion to retrieve more comments)?";
                        }
                        var delete_button = divels[_i].querySelectorAll('form input[value="removed"]~span.option.error a.yes,a[onclick^="return big_mod_action(jQuery(this), -1)"]');
                        // form input[value="removed"]~span.option.error a.yes -- finds the yes for normal deleting comments.
                        // a.pretty-button.neutral finds the 'remove' button for flagged comments
                        if (confirm("Are you sure you want to nuke the following " + delete_button.length + comment_str)) {
                            for (var indx=0; indx < continue_thread.length; indx++) {
                                var elmnt = continue_thread[indx];
                                setTimeout(function() {
                                    var event = document.createEvent('UIEvents');
                                    event.initUIEvent('click', true, true, window, 1);
                                    elmnt.dispatchEvent(event);
                                }, 2000*indx); // wait two seconds before each ajax call before clicking each "load more comments"
                            }
                            if(indx > 0) {
                                setTimeout(function() {
                                    delete_function(comment_ids[_i])
                                }, 2000*(indx + 2)); // wait 4s after last ajax "load more comments"
                            } else {
                                delete_function(comment_ids[_i]); // call immediately if not "load more comments"
                            }
                        }
                    }
                })(i)); // end of IIFE (immediately invoked function expression)
            }
        }
    }
  },

  //nuke (djimbob)
  delete_function: function(thread_root) {
      var elmnts = document.getElementsByClassName('id-'+thread_root)[0].querySelectorAll('form input[value="removed"]~span.option.error a.yes,a[onclick^="return big_mod_action(jQuery(this), -1)"]');
      for(var i=0; i < elmnts.length; i++) {
          setTimeout((function(_elmnt) {
                  return function() {
                      var event = document.createEvent('UIEvents');
                      event.initUIEvent('click', true, true, window, 1);
                      _elmnt.dispatchEvent(event);
                  };
              })(elmnts[i]), 1500*i); // 1.5s timeout prevents overloading reddit.
      };
  }
};

// initialize when document loaded
jQuery(document).ready(function() {
    RaaW.init();
    RaaW.Nuke.init();
});