// ==UserScript==
// @name ii-block
// @namespace http://enquirer.improbableisland.com/dokuwiki/doku.php?id=greasemonkey
// @author Full Metal Lion
// @description Blocks a user in chat
// @version 2.1
// @match *://*.improbableisland.com/*
// @exclude *://enquirer.improbableisland.com/*
// @icon http://improbableisland.com/favicon.ico
// @grant none
// ==/UserScript==
//USER-SET VARIABLES:
var blockedUserIDs = []; //put users ids here, separated by commas (eg [100001,47,201])
var showBlankLines = true; //set this to false if you want no indication that a message was blocked
//INTERNAL PROGRAM LOGIC:
//helper function
function delL(element){
if(element && element.className != "singlecomment"){
delL(element.previousSibling);
element.remove();
}
}
//the actual function of interest
function removeBlockedMessages(){
for (var x of blockedUserIDs){
for (var m of document.querySelectorAll("a[href='bio.php?char="+x+"']")){
//you'd think that we could just call .parent.remove() on the things we find
// but actually the chat html is hot garbage and nested improperly, so we have to do this
delL(m.previousSibling);
if(showBlankLines && m.innerHTML){ //there are actually two elements per comment, one empty.
//we only want one (else we'd get double spacing) so we pick the nonempty one.
m.before(document.createElement('p'));
}
}
for (var p of ps){
var re = RegExp('[\\w\\W]*?
','gi');
var egregiousExtraMouseoverLink = RegExp('','gi');
var html = p.innerHTML.replace(egregiousExtraMouseoverLink,'');
p.innerHTML = html.replace(re,'');
}
}
}
var ps = []; //find chat areas on page load
for (var c of document.getElementsByClassName("singlecomment")){
var p = c.parentNode;
if(p&&!ps.includes(p)&&p.className!="singlecomment"){
ps.push(p);
}
}
removeBlockedMessages(); //invoke function when page loads
//run removeBlockedMessages whenever an ajax chat auto-update completes)
//(This is the part that doesn't work in greasemonkey without later shenanigans)
//adapted from from https://stackoverflow.com/a/29293383 :
(function(open) {
window.XMLHttpRequest.prototype.open = function() {
this.addEventListener("readystatechange", function() {
if(this.readyState == 4 && this.responseURL.startsWith("https://www.improbableisland.com/ajaxchat.php")){
removeBlockedMessages();
}
}, false);
open.apply(this, arguments);
};
})(window.XMLHttpRequest.prototype.open);
//If we're running on a system that supports @grant none, then we're done.
//However, the greasemonkey extension on Firefox does not
//so we must do something special to support it
//Here I use the Content Scope Runner as found in
//https://wiki.greasespot.net/index.php?title=Content_Scope_Runner&oldid=7215
if ('undefined' == typeof __PAGE_SCOPE_RUN_II_BLOCK_) {
(function page_scope_runner() {
// If we're _not_ already running in the page, grab the full source
// of this script.
var my_src = "(" + page_scope_runner.caller.toString() + ")();";
// Create a script node holding this script, plus a marker that lets us
// know we are running in the page scope (not the Greasemonkey sandbox).
// Note that we are intentionally *not* scope-wrapping here.
var script = document.createElement('script');
script.setAttribute("type", "text/javascript");
script.textContent = "var __PAGE_SCOPE_RUN_II_BLOCK_ = true;\n" + my_src;
// Insert the script node into the page, so it will run, and immediately
// remove it to clean up. Use setTimeout to force execution "outside" of
// the user script scope completely.
setTimeout(function() {
document.body.appendChild(script);
document.body.removeChild(script);
}, 0);
})();
// Stop running, because we know Greasemonkey actually runs us in
// an anonymous wrapper.
return;
}