Greasy Fork

ニコニコ静画NGスクリプト

ニコニコ静画でNGユーザの投稿を非表示にする

当前为 2020-06-11 提交的版本,查看 最新版本

// ==UserScript==
// @name ニコニコ静画NGスクリプト
// @match *://seiga.nicovideo.jp/search/*
// @match *://seiga.nicovideo.jp/tag/*
// @description ニコニコ静画でNGユーザの投稿を非表示にする
// @version 20200612
// @namespace https://greasyfork.org/users/585074
// ==/UserScript==

var controll = document.getElementsByClassName("controll")[0];
const ng_config_button = document.createElement("input");
ng_config_button.id = "ng_config_button";
ng_config_button.type = "button";
ng_config_button.value = "静画NG設定";
ng_config_button.style.cssText = "background-color:red; padding: 3px; font-size: 14px";
controll.insertBefore(ng_config_button, document.getElementsByClassName("sort")[0]);

var ng_list_db = [];
var id_name_list = [];
var id_query_flag = 0;
loadNgData();

const ng_dialog = document.createElement("div");
ng_dialog.id = "ng_dialog";
ng_dialog.style.cssText = "margin-bottom:1em; position:fixed; width:40%; height:40%; line-height:1.5em; display:none; flex-direction:column; justify-content:center; background-color:gray; z-index:1";

const ng_dialog_top = document.createElement("div");
ng_dialog_top.style.cssText = "display:flex; flex-direction:row;";

const ng_types = document.createElement("select");
ng_types.style.cssText = "font-size:14px; margin-top:1em; margin-bottom:1em; margin-left:1em;";
ng_types.innerHTML = `<option>NGユーザーID</option>
                      <option>NGユーザー名</option>`;

const ng_durations = document.createElement("select");
ng_durations.style.cssText = "font-size:14px; margin-top:1em; margin-bottom:1em; margin-left:4em;";
ng_durations.innerHTML = `<option>設定期間:永久</option>
                          <option>設定期間:1週間</option>
                          <option>設定期間:1ヶ月間</option>
                          <option>設定期間:3ヶ月間</option>
                          <option>設定期間:6ヶ月間</option>
                          <option>設定期間:1年間</option>
                          <option>設定期間:3年間</option>`;

const ng_close_button = document.createElement("input");
ng_close_button.type = "button";
ng_close_button.style.cssText = "font-size:18px; margin-top:0.5em; margin-bottom:0.5em; margin-left:4em; padding-left:1em; padding-right:1em;";
ng_close_button.value = "閉じる";
ng_close_button.onclick = function () {
    ng_dialog.style.display = "none";
}

const ng_dialog_middle = document.createElement("div");
ng_dialog_middle.style.cssText = "width:100%; height:100%; margin-bottom:1em; display:flex; flex:auto; flex-direction:row;";

const ng_list = document.createElement("select");
ng_list.style.cssText = "width:90%; margin-left:1em; margin-right:1em;";
ng_list.multiple = "multiple";
ng_list.size = 14;
updateNgList();

const ng_operation_buttons = document.createElement("p");
ng_operation_buttons.style.cssText = "display:flex; flex:auto; flex-direction:column;";
const ng_add_button = document.createElement("input");
ng_add_button.style.cssText = "font-size:18px; width:4em; margin-right:1em;";
ng_add_button.type = "button";
ng_add_button.value = "追加";
const ng_delete_button = document.createElement("input");
ng_delete_button.style.cssText = "font-size:18px; width:4em; margin-right:1em; margin-top:1em;";
ng_delete_button.type = "button";
ng_delete_button.value = "削除";

ng_dialog_top.appendChild(ng_types);
ng_dialog_top.appendChild(ng_durations);
ng_dialog_top.appendChild(ng_close_button);
ng_dialog.appendChild(ng_dialog_top);
ng_dialog_middle.appendChild(ng_list);
ng_operation_buttons.appendChild(ng_add_button);
ng_operation_buttons.appendChild(ng_delete_button);
ng_dialog_middle.appendChild(ng_operation_buttons);
ng_dialog.appendChild(ng_dialog_middle);
controll.appendChild(ng_dialog);

ng_config_button.onclick = function(){
    ng_dialog.style.display = "flex";
};

ng_add_button.onclick = function(){
    var ng_user = window.prompt(ng_types.value + "を入力してください", "");
    var ng_duration = ng_durations.value;
    var end_date = new Date();
    if (ng_duration == "設定期間:永久"){
        end_date.setFullYear(4000);
    }else if (ng_duration == "設定期間:1週間"){
        end_date.setDate(end_date.getDate() + 7);
    }else if (ng_duration == "設定期間:1ヶ月間"){
        end_date.setDate(end_date.getDate() + 30);
    }else if (ng_duration == "設定期間:3ヶ月間"){
        end_date.setMonth(end_date.getMonth() + 3);
    }else if (ng_duration == "設定期間:6ヶ月間"){
        end_date.setMonth(end_date.getMonth() + 6);
    }else if (ng_duration == "設定期間:1年間"){
        end_date.setFullYear(end_date.getFullYear() + 1);
    }else if (ng_duration == "設定期間:3年間"){
        end_date.setFullYear(end_date.getFullYear() + 3);
    }

    var opt = document.createElement("option");
    opt.text = formatNgInfo(ng_types.value, dateString(end_date), ng_user);
    var ng_info = { user : ng_user, type : ng_types.value, date : dateString(end_date) };
    ng_list_db.push(ng_info);
    if (ng_types.value == "NGユーザーID"){
        var ng_user_name = getUserName(ng_user);
        var id_name_obj = { id : ng_user, name : ng_user_name };
        id_name_list.push(id_name_obj);
    }
    updateNgList();
    saveNgData();
};

ng_delete_button.onclick = function(){
    var ng_info = parseNgInfo(ng_list.value);
    ng_list_db.splice(ngListIndexOf(ng_info.user), 1);
    updateNgList();
    saveNgData();
};

function dateString(date){
    var year = date.getFullYear();
    var month = date.getMonth() + 1;
    var day = date.getDate();
    var toofar = new Date(3000, 11, 31, 23, 59, 59, 999);
    if (date > toofar) return "9999/12/31";
    return year + "/" + month + "/" + day;
}

function formatNgInfo(type, date, user){
    return "[" + type + "]" + date + "まで" + user;
}

function parseNgInfo(nginfo_text){
    var type, date, user;
    type = nginfo_text.substr(1, nginfo_text.indexOf("]") - 1);
    date = nginfo_text.substr(nginfo_text.indexOf("]") + 1, nginfo_text.indexOf("まで") - 1 - nginfo_text.indexOf("]"));
    user = nginfo_text.substr(nginfo_text.indexOf("まで") + "まで".length);
    return { user : user, type : type, date : date };
}

function saveNgData(){
    localStorage.setItem("nicovideo_seiga_ng", JSON.stringify(ng_list_db));
}

function loadNgData(){
    //ブラウザに保存したNGリストデータをロード
    var db = localStorage.getItem("nicovideo_seiga_ng");
    if (db == null){
        ng_list_db = [];
    }else{
        ng_list_db = JSON.parse(localStorage.getItem("nicovideo_seiga_ng"));
    }
    //期限切れのNG指定があったら削除
    var today = new Date();
    for (var i = ng_list_db.length - 1; i >= 0; i--){
        var yy_mm_dd = ng_list_db[i].date.split("/");
        var end_date = new Date(yy_mm_dd[0], yy_mm_dd[1], yy_mm_dd[2]);
        if (today > end_date){
            ng_list_db.splice(i, 1);
        }
    }

    //ユーザID形式の項目があったら対応するユーザ名を取得
    if (id_query_flag == 0){
        for (var j = 0; j < ng_list_db.length; j++){
            if (ng_list_db[j].type == "NGユーザーID"){
                var name = getUserName(ng_list_db[j].user);
                var obj = { id : ng_list_db[j].user, name : name };
                id_name_list.push(obj);
            }
        }
        id_query_flag = 1;
    }
}

function updateNgList(){
    ng_list.innerHTML = "";
    for (var i = 0; i < ng_list_db.length; i++) {
        var opt = document.createElement("option");
        opt.text = formatNgInfo(ng_list_db[i].type, ng_list_db[i].date, ng_list_db[i].user);
        ng_list.appendChild(opt);
    }
}

function ngListIndexOf(user){
    for(var i = 0; i < ng_list_db.length; i++){
        if (ng_list_db[i].user == user) return i;
    }
    return -1;
}

function requestXml(url){
    var xhr = new XMLHttpRequest();
    var recv_flag = 0;
    xhr.onreadystatechange = function (){
	    switch(xhr.readyState){
	    case 4:
	    	if(xhr.status == 0){
	    		alert("XHR 通信失敗");
	    	}else{
	    		if((200 <= xhr.status && xhr.status < 300) || (xhr.status == 304)){
	    			recv_flag = 1;
	    		}else{
	    			alert("その他の応答:" + xhr.status);
	    		}
	    	}
	    	break;
	    }
    };
    xhr.open("GET", url, false);
    xhr.send(null);
    var cnt = 0;
    while(recv_flag == 0){
        if (recv_flag == 1) break;
        cnt +=1;
        setTimeout(() => {;}, 100);
        if (cnt > 10) break;
    }
    var http = xhr.responseXML;
    xhr.abort();
    return http;
}

function getUserName(id){
    var username_query_url = "https://seiga.nicovideo.jp/api/user/info?id=" + id;
    var xml = requestXml(username_query_url);
    var nickname = xml.documentElement.getElementsByTagName("nickname")[0];
    return nickname.textContent;
}

function isNgUser(user){
    for (var i = 0; i < ng_list_db.length; i++){
        if (ng_list_db[i].type == "NGユーザー名") {
            if (user == ng_list_db[i].user) return true;
        }else if(ng_list_db[i].type == "NGユーザーID"){
            for (var j = 0; j < id_name_list.length; j++){
                if(id_name_list[j].id == ng_list_db[i].user){
                    if (id_name_list[j].name == user) return true;
                }
            }
        }
    }
    return false;
}

//ページロード時の該当項目非表示処理
var users = document.getElementsByClassName('user');
for (var i = 0; i < users.length; i++) {
    var user_name = users[i].innerHTML;
    if (isNgUser(user_name)) {
        var parent = users[i].parentNode.parentNode.parentNode;
        parent.style.visibility = 'hidden';
    }
}