// ==UserScript== // @name ニコニコ静画NGスクリプト // @match *://seiga.nicovideo.jp/search/* // @match *://seiga.nicovideo.jp/tag/* // @description ニコニコ静画でNGユーザの投稿を非表示にする // @version 20200612 // @namespace https://greasyfork.org/users/585074 // @downloadURL none // ==/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 = ` `; 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 = ` `; 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'; } }