Greasy Fork is available in English.

Open 2ch NG

「おーぷん2ちゃんねる」でNGネーム・アイコンに関連するレスを見えなくする

このスクリプトの質問や評価の投稿はこちら通報はこちらへお寄せください。
// ==UserScript==
// @name         Open 2ch NG
// @namespace    https://greasyfork.org/ja/users/426180
// @version      1.0
// @description  「おーぷん2ちゃんねる」でNGネーム・アイコンに関連するレスを見えなくする
// @author       Coda2001
// @match        *://*.open2ch.net/test/read.cgi/*
// @grant        none
// ==/UserScript==

'use strict';

var ng_list = [];
var NGID = [];
var NGIDnum = 0;

//NGリスト取得関数
function getNGlist(){
    if(localStorage.NGlist === undefined){
        localStorage.NGlist = [""];
        return [""];
    }else{
        return localStorage.NGlist.split("\n");
    }
}

//親要素を取得するための関数
function getParentNodeByName(elem,name){
    var i = 0;
    var tgt = new Array;
    tgt[0] = elem;
    while(tgt[i].tagName !== "BODY"){
        if(tgt[i].tagName === name){
            return tgt[i];
        }
        tgt[i+1] = tgt[i].parentNode;
        i++;
    }
    return;
}

//コテNG
function thread(){
    document.querySelectorAll("a.num").forEach(function(elem){
        var got_name = elem.querySelector("font").innerHTML;
        const id = elem.getAttribute("val");
        if (got_name == null || got_name == undefined) {
            got_name = "";
        }
        for(let i = 0;i < ng_list.length;i++){
            const ngword = ng_list[i];
            if(ngword === ""){
                continue;
            }
            const index = got_name.includes(ngword);
            if(index === true){
                if(NGID.indexOf(id) === -1){
                    NGID[NGID.length] = id;
                }
                break;
            }
        }
        return;
    });
}

//アイコンNG
function icon(){
    document.querySelectorAll("div.faceicon").forEach(function(elem){
        const tgt = getParentNodeByName(elem,"DL");
        const id = tgt.querySelector("a.num").getAttribute("val");
        if(NGID.indexOf(id) === -1){
            NGID[NGID.length] = id;
        }
        return;
    });
}

//NGレスに安価飛ばすレスをNG
function ankNg(){
    const thr = document.querySelector("div.thread");
    thr.querySelectorAll("a._ank").forEach(function(elem){
        const tgt = getParentNodeByName(elem,"DL");
        const id = tgt.querySelector("a.num").getAttribute("val");
        const ankNum = elem.textContent.slice(2);
        if(NGID.indexOf(ankNum) !== -1){
            if(NGID.indexOf(id) === -1){
                NGID[NGID.length] = id;
            }
        }
        return;
    });
}

//安価逆参照の中のNGレス除去
function removeNG(elm){//安価逆参照要素の中のNGレスを取り除く関数
    var num = 0;
    elm.querySelectorAll("a.num").forEach(function(elem){
        const id = elem.getAttribute("val");
        if(NGID.indexOf(id) !== -1){
            const tgt_name = getParentNodeByName(elem,"DT");
            const tgt_comment = tgt_name.nextElementSibling;
            tgt_name.remove();
            tgt_comment.remove();
            num++;
        }
    });
    if(num > 0){
        addMassage("レスを"+num+"件除去しました.");
    }
}
function execute(event){//押した要素にだけremoveNGする関数
    const evpl = event.target;
    const tgt = getParentNodeByName(evpl,"DIV");
    setTimeout(function(){removeNG(tgt);},200);//要改善
}
function addNG(){//全ての安価逆参照要素にcheckNGを追加する関数
    document.querySelectorAll("div.aresdiv").forEach(function(elem){
        elem.addEventListener('click',execute);
    });
}

//NGレスを消す
function removeNg(){
    document.querySelectorAll("a.num").forEach(function(elem){
        const num = elem.getAttribute("val");
        if(NGID.indexOf(num) !== -1){
            const tgt = getParentNodeByName(elem,"DL");
            tgt.remove();
        }
    });
}

//ページを隠す・表示
function visible(val){
    document.querySelector("html").style.visibility = val;
}

//操作ボックス
function divCreate(){
    var win = document.createElement("div");
    var bod = document.createElement("div");
    var tab = document.createElement("div");
    var log_tab = document.createElement("div");
    var config_tab = document.createElement("div");
    var log_bod = document.createElement("div");
    var log = document.createElement("div");
    var run_btn = document.createElement("input");
    var config_bod = document.createElement("div");
    var config = document.createElement("textarea");
    var config_btn = document.createElement("div");
    var config_btn1 = document.createElement("input");
    var config_btn2 = document.createElement("input");
    win.id = "NGbox";
    win.style = "z-index:20;position:fixed;bottom:60px;right:0px;width:220px;font-size:9pt;";
    win.innerHTML = '<div style="border:1px solid;background:#030;"><div style="color:white;padding:3px;"> Open 2ch NG</div></div>';
    bod.style = "background:#ddffdd;border:1px solid;";
    tab.style = "display:flex;flex-direction:row;";
    log_tab.style = "text-align:center;width:50%;cursor:pointer;padding:3px;background:#ddffdd;font-size:9pt;";
    log_tab.innerHTML = "NGログ";
    log_tab.addEventListener('click',()=>{
        log_bod.style.display = "";
        log_tab.style.background = "#ddffdd";
        config_bod.style.display = "none";
        config_tab.style.background = "#5ad25a";
    });
    config_tab.style = "text-align:center;width:50%;cursor:pointer;padding:3px;background:#5ad25a;font-size:9pt;";
    config_tab.innerHTML = "NGリスト";
    config_tab.addEventListener('click',()=>{
        log_bod.style.display = "none";
        log_tab.style.background = "#5ad25a";
        config_bod.style.display = "";
        config_tab.style.background = "#ddffdd";
    });
    log_bod.style = "";
    log.id = "NGlog";
    log.innerHTML = "おーぷん2ちゃんねるNG機能";
    log.style = "background:white;overflow-y:scroll;margin:5px;height:80px;width:210px;";
    run_btn.setAttribute("type","button");
    run_btn.setAttribute("value","更新");
    run_btn.style = "cursor:pointer;display:block;margin:0px 5px 5px auto;"
    run_btn.addEventListener("click",() =>{
        doNg();
        massage();
    });
    config_bod.style = "display:none;";
    config.id = "NGlist";
    config.value = localStorage.NGlist;
    config.style = "background:white;overflow-y:scroll;margin:5px;height:80px;width:210px;border:none;resize:none;font-size:9pt;";
    config.placeholder = "1行に1つずつNGする名前を入力";
    config_btn.style = "text-align:right";
    config_btn1.setAttribute("type","button");
    config_btn1.setAttribute("value","設定");
    config_btn1.style = "cursor:pointer;displayinline-:block;margin:0px 5px 5px auto;"
    config_btn1.addEventListener("click",() =>{
        var gotList = document.getElementById("NGlist").value;
        while(gotList.startsWith("\n") === true){
            gotList = gotList.replace("\n","");
        }
        while(gotList.indexOf("\n\n") !== -1){
            gotList = gotList.replace("\n\n","\n");
        }
        localStorage.NGlist = gotList;
        ng_list = getNGlist();
        document.getElementById("NGlist").value = localStorage.NGlist;
    });
    config_btn2.setAttribute("type","button");
    config_btn2.setAttribute("value","リストの更新");
    config_btn2.style = "cursor:pointer;display:inline-block;margin:0px 5px 5px auto;"
    config_btn2.addEventListener("click",() =>{
        document.getElementById("NGlist").value = localStorage.NGlist;
    });
    win.appendChild(bod);
    bod.appendChild(tab);
    tab.appendChild(log_tab);
    tab.appendChild(config_tab);
    bod.appendChild(log_bod);
    log_bod.appendChild(log);
    log_bod.appendChild(run_btn);
    bod.appendChild(config_bod);
    config_bod.appendChild(config);
    config_bod.appendChild(config_btn);
    config_btn.appendChild(config_btn2);
    config_btn.appendChild(config_btn1);
    return win;
}
function addMassage(text){//NGログにメッセージを追加する
    const div = document.getElementById("NGlog");
    div.innerHTML = "▶" + text + "<br>" + div.innerHTML.replace("▶","");
}

//ページ読み込み時に実行
function main (){
    visible("hidden");
    const checkInterval = setInterval(()=>{
        if(document.readyState!=="loading"){
            clearInterval(checkInterval);
            document.body.appendChild(divCreate());
            doNg();
            massage();
            visible("");
        }
    },100);
}

//NG関数まとめ
function doNg(){
    ng_list = getNGlist();
    thread();
    icon();
    ankNg();
    addNG();
    removeNg();
}

//ページ読み込み時・手動更新時のメッセージ
function massage(){
    var num = NGID.length - NGIDnum;
    if(num !== 0){
        var str = "";
        for(let i = NGIDnum;i < NGID.length;i++){
            str = str + NGID[i] + ",";
        }
        addMassage("レスを"+num+"件削除しました.<br>▶"+str);
        NGIDnum = NGID.length;
    }else{
        addMassage("NGレスはありません.");
    }
}

//ページ読み込み時に実行
const url = window.location.href;
console.log("[Open_2ch_NG] run");
document.addEventListener('DOMContentloaded',main());

//新着時に実行
var flag = 0;
const target = document.querySelector("title");
const observer = new MutationObserver( function(mutations) {
    mutations.forEach(function(mutation) {
        if(flag%2 === 0){
            setTimeout(function(){
                doNg();
                var num = NGID.length - NGIDnum;
                if(num !== 0){
                    var str = "";
                    for(let i = NGIDnum;i < NGID.length;i++){
                        str = str + NGID[i] + ",";
                    }
                    addMassage("NGレスです.<br>▶"+str);
                    NGIDnum = NGID.length;
                }else{
                    addMassage("NGレスではありません.");
                }
            },300);
        }
        flag++;
    });
});
const config = {attributes: true, childList: true, characterData: true};
observer.observe(target, config);