Mitbbs-bot-blocker

Manages and blocks bot generated content. Inspired by Smalltalk80's original GM script, http://userscripts-mirror.org/scripts/review/78633

Tendrás que instalar una extensión para tu navegador como Tampermonkey, Greasemonkey o Violentmonkey si quieres utilizar este script.

Necesitarás instalar una extensión como Tampermonkey o Violentmonkey para instalar este script.

Necesitarás instalar una extensión como Tampermonkey o Violentmonkey para instalar este script.

Necesitarás instalar una extensión como Tampermonkey o Userscripts para instalar este script.

Necesitará instalar una extensión como Tampermonkey para instalar este script.

Necesitarás instalar una extensión para administrar scripts de usuario si quieres instalar este script.

(Ya tengo un administrador de scripts de usuario, déjame instalarlo)

Necesitará instalar una extensión como Stylus para instalar este estilo.

Necesitará instalar una extensión como Stylus para instalar este estilo.

Necesitará instalar una extensión como Stylus para instalar este estilo.

Necesitará instalar una extensión del gestor de estilos de usuario para instalar este estilo.

Necesitará instalar una extensión del gestor de estilos de usuario para instalar este estilo.

Necesitará instalar una extensión del gestor de estilos de usuario para instalar este estilo.

(Ya tengo un administrador de estilos de usuario, déjame instalarlo)

// ==UserScript==
// @name         Mitbbs-bot-blocker
// @namespace    http://tampermonkey.net/
// @version      0.8 
// @description  Manages and blocks bot generated content. Inspired by Smalltalk80's original GM script, http://userscripts-mirror.org/scripts/review/78633
// @author       术版小吃
// @match        http://www.mitbbs.com/*
// @match        https://www.mitbbs.com/*
// @grant        GM_addStyle
// @run-at       document-idle
// ==/UserScript==
//debugger;
(function() {
'use strict';

var storageKey = 'mitbbs.blocklist';
var pageType = locationGuesser();

function locationGuesser() {
  var pageType = void 0;
  var url = window.location.href;
  if (url.indexOf('article') > -1) {
    pageType = 1;
  } else if (url.indexOf('bbsdoc') > -1) {
    pageType = -1;
  } else {
    pageType = 0;
  }

  return pageType;
}

function getBlocklist() {
  var blockList = localStorage.getItem(storageKey);
  if (blockList === null) {
    setBlocklist([]);
    blockList = localStorage.getItem(storageKey);
  }

  try {
    blockList = JSON.parse(blockList);
  } catch (error) {
    blockList = [];
    setBlocklist(blockList);
  }

  blockList = Array.isArray(blockList) ? blockList : [];
  return blockList;
}

function setBlocklist(idNameList) {
  // remove duplicate items
  // todo: babel output for this one doesn't really work, have to revert back to old fashion way
  // idNameList = [...new Set(idNameList)]
  var uniqueidNameList = idNameList.filter(function (elem, index, self) {
    return index === self.indexOf(elem);
  });
  uniqueidNameList = uniqueidNameList.sort(function (a, b) {
    // defer from localeCompare for better browser support
    if (a.toLowerCase() < b.toLowerCase()) return -1;
    if (a.toLowerCase() > b.toLowerCase()) return 1;
    return 0;
  });
  localStorage.setItem(storageKey, JSON.stringify(uniqueidNameList));
  document.getElementById('blockListInput').value = uniqueidNameList;
}

function getBlockFlag() {
  var blockFlag = localStorage.getItem(storageKey + '.flag');
  if (blockFlag === null) {
    setBlockFlag(0);
    blockFlag = localStorage.getItem(storageKey + '.flag');
  }
  //  js, just being js
  return parseInt(blockFlag);
}

function setBlockFlag(flag) {
  localStorage.setItem(storageKey + '.flag', flag);
}

function changePostVisibility() {
  var blockList = getBlocklist();
  var flag = getBlockFlag();
  // if list is not empty
  var counter = 0;
  if (blockList) {
    var taolunDiv = document.querySelector('td.taolun_leftright tbody');
    // yeah yeah yeah magic number, whatever
    // this will miss the first one though, nice try langfang coder
    var userIDtdNodeList = taolunDiv.querySelectorAll('td:nth-child(5)');
    userIDtdNodeList.forEach(function (td) {
      // damn, now i miss jquery/zepto
      var id = td.querySelector('a.news') ? td.querySelector('a.news').innerHTML.replace(/\s/g, '') : null;

      //  reset all reply to visible. This is a hack-ish method to fix content not being displayed after userID has been removed from blocklist.
      //  TODO: maybe in the near future, we should keep a local copy of blocklist so that we can compare the changes and show/hide content intelligently, maybe
      td.parentNode.style.display = '';

      //  yeah, nested if statements
      if (blockList.indexOf(id) > -1) {
        if (flag) {
          td.parentNode.style.display = 'none';
          counter += 1;
        } else {
          td.parentNode.style.display = '';
        }
      }
    });
    counter = flag ? counter : 0;
    document.getElementById('blockCounter').innerHTML = counter;
  }
}

function changeReplyVisibility() {
  //  now we on individual post page
  var blockList = getBlocklist();
  var flag = getBlockFlag();
  var counter = 0;
  var sideBarBG = document.querySelectorAll('td.wenzhang_bg');
  sideBarBG.forEach(function (reply) {
    var post = reply.parentElement.parentElement.parentElement.parentElement.parentElement;
    //  another magic number!
    var userMenu = post.querySelector('td.jiahui-4 td[width="83%"]');
    var userID = post.querySelector('td.wenzhang strong a').innerHTML.replace(/\s/g, '');
    var hasButton = userMenu.lastChild.innerHTML !== undefined;
    if (!hasButton) {
      var blockButton = document.createElement('span');
      blockButton.setAttribute('class', 'buttonHolder');
      blockButton.innerHTML = '&nbsp;&nbsp;<button class="addToBlock" title="' + userID + '">屏蔽!</button>';
      userMenu.appendChild(blockButton);
    }
    //  reset all reply to visible. This is a hack-ish method to fix content not being displayed after userID has been removed from blocklist.
    //  TODO: maybe in the near future, we should keep a local copy of blocklist so that we can compare the changes and show/hide content intelligently, maybe
    post.style.display = '';

    if (blockList.indexOf(userID) > -1) {
      if (flag) {
        post.style.display = 'none';
        counter += 1;
      } else {
        post.style.display = '';
      }
    }
    counter = flag ? counter : 0;
    document.getElementById('blockCounter').innerHTML = counter;
  });

  var allBlockButton = document.querySelectorAll('.addToBlock');
  Array.from(allBlockButton).forEach(function (button) {
    var userID = button.getAttribute('title');
    button.addEventListener('click', function () {
      var yesBlock = confirm('Block ' + userID + ' ?');
      if (yesBlock) {
        blockList.push(userID);
        setBlocklist(blockList);
        document.getElementById('blockListInput').value = getBlocklist().join();
        toggleBlockedContent();
      }
    });
  });
}

function toggleBlockedContent() {
  document.getElementById('isBlocking').checked ? setBlockFlag(1) : setBlockFlag(0);
  switch (pageType) {
    case 1:
      changeReplyVisibility();
      break;
    case -1:
      changePostVisibility();
      break;
  }
}

function changeBlockListVisibility() {
  var notVisible = document.getElementById('blockListPop').style.display === 'none';
  if (notVisible) {
    document.getElementById('blockListInput').value = getBlocklist().join();
    document.getElementById('blockListPop').style.display = '';
  } else {
    document.getElementById('blockListPop').style.display = 'none';
  }
}

function updateBlockList() {
  var newBlockList = document.getElementById('blockListInput').value;
  //  remove line break, space, trailing comma
  newBlockList = newBlockList.replace(/(\r\n|\n|\r)/gm, '').replace(/\s/g, '').replace(/,+$/, '');
  newBlockList = newBlockList.split(',');
  setBlocklist(newBlockList);

  // re-filter existing content
  toggleBlockedContent();
}

function hideBlockList() {
  document.getElementById('blockListPop').style.display = 'none';
}

function prepPage() {
  var flag = getBlockFlag();
  getBlocklist();
  if (flag) {
    document.getElementById('isBlocking').checked = true;
    toggleBlockedContent();
  }
}

function pageOnLoad() {
  //  build blocker control gui
  var blockerDiv = document.createElement('div');
  blockerDiv.innerHTML = '<button id="showBlocklist">黑名单</button><input type="checkbox" id="isBlocking" /><span id="blockCounter" title="Currently Blocked"></span>';
  blockerDiv.style.cssText = 'position:fixed; bottom:2em; right:0.5em; width:9em; padding:0.5em; border-radius:0.25em; background-color:#D7EAF9; box-shadow:2px 2px 4px 0px rgba(0,0,0,0.5); text-align:center; cursor:pointer;';
  document.body.appendChild(blockerDiv);

  document.getElementById('showBlocklist').addEventListener('click', changeBlockListVisibility);
  document.getElementById('blockCounter').style.cssText = 'padding:0 4px; font-weight:bold';
  document.getElementById('isBlocking').addEventListener('change', toggleBlockedContent);

  //  block list
  var blockListDiv = document.createElement('div');
  blockListDiv.setAttribute('id', 'blockListPop');
  blockListDiv.innerHTML = '<span>修改ID,用逗号分隔,大小写敏感!</span>' + '<br/>' + '<textarea rows="10" cols="40" id="blockListInput"></textarea>' + '<br/>' + '<button id="updateBlockList">Update</button><span style="width:2em"></span><button id="closePop">Close</button>';
  blockListDiv.style.cssText = 'position:fixed; bottom:5.3em; right:0.5em; padding:0.5em; border-radius:0.25em; background-color:#D7EAF9; box-shadow:2px 2px 4px 0px rgba(0,0,0,0.5); text-align:center; display:none';
  document.body.appendChild(blockListDiv);

  document.getElementById('updateBlockList').addEventListener('click', updateBlockList);
  document.getElementById('closePop').addEventListener('click', hideBlockList);

  prepPage();
}

function ready(fn) {
  if (document.readyState !== 'loading') {
    fn();
  } else {
    document.addEventListener('DOMContentLoaded', fn);
  }
}

ready(pageOnLoad);
})();