您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
ニコニコ静画でNGユーザの投稿を非表示にする
// ==UserScript== // @name ニコニコ静画NGスクリプト // @match *://seiga.nicovideo.jp/* // @match *://seiga.nicovideo.jp/search/* // @match *://seiga.nicovideo.jp/tag/* // @match *://seiga.nicovideo.jp/illust/* // @match *://seiga.nicovideo.jp/my/personalize* // @description ニコニコ静画でNGユーザの投稿を非表示にする // @license MIT License Copyright (c) 2020 Tennosuke Tokoro // @license このスクリプトはkengo312氏のNico Nico Ranking NG (MIT License)を流用しています。 // @version 202007190 // @namespace https://greasyfork.org/users/585074 // ==/UserScript== var i; var parent_element, mode; if(location.href.match(/seiga.nicovideo.jp\/search/)){ mode = "キーワード検索"; parent_element = document.getElementById("usearch_form"); }else if(location.href.match(/seiga.nicovideo.jp\/my\/personalize/)){ mode = "定点観測"; parent_element = document.getElementsByClassName("sg_pankuzu")[0]; }else if(location.href.match(/seiga.nicovideo.jp\/tag/)){ mode = "タグ検索"; parent_element = document.getElementsByClassName("sg_pankuzu")[0]; }else if(location.href.match(/seiga.nicovideo.jp\/illust\/ranking\/point\/.*\/g_.*/)){ mode = "ランキング・個別"; parent_element = document.getElementsByClassName("sg_pankuzu")[0]; }else if(location.href.match(/seiga.nicovideo.jp\/illust\/ranking/)){ mode = "ランキング・まとめ"; parent_element = document.getElementsByClassName("sg_pankuzu")[0]; }else if(location.href.match(/seiga.nicovideo.jp\/illust\/list/)){ mode = "すべてのイラスト"; parent_element = document.getElementsByClassName("sg_pankuzu")[0]; }else if(location.href.match(/seiga.nicovideo.jp\/seiga\/im/)){ mode = "投稿ページ"; parent_element = document.getElementsByClassName("sg_pankuzu")[0]; }else{ mode = "トップページ"; parent_element = document.getElementsByClassName("sg_pankuzu")[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-left:0.5em; padding-right:0.5em; padding-top:1px; padding-bottom:1px; font-size:12px; margin-left:1em;"; parent_element.appendChild(ng_config_button); //NG設定画面 const ng_dialog = document.createElement("div"); ng_dialog.id = "ng_dialog"; ng_dialog.style.cssText = "margin-bottom:1em; position:fixed; width:auto; height:40%; line-height:1.5em; display:none; flex-direction:column; justify-content:center; background-color:gray; z-index:10"; 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ユーザー名</option> <option>NGユーザーID</option> <option>NG静画ID</option>`; const ng_durations = document.createElement("select"); ng_durations.style.cssText = "font-size:14px; margin-top:1em; margin-bottom:1em; margin-left:1em;"; 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:1em; padding-left:1em; padding-right:1em;"; ng_close_button.value = "閉じる"; ng_close_button.onclick = function () { ng_dialog.style.display = "none"; } const ng_onoff_button = document.createElement("input"); ng_onoff_button.type = "button"; ng_onoff_button.style.cssText = "font-size:18px; background-color:steelblue; width:6em; margin-top:0.5em; margin-bottom:0.5em; margin-left:1em; margin-right:1em; padding-left:1em; padding-right:1em;"; ng_onoff_button.value = "一時停止"; 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:auto; margin-left:1em; margin-right:1em;"; ng_list.multiple = "multiple"; ng_list.size = 14; const ng_operation_area = document.createElement("p"); ng_operation_area.style.cssText = "display:flex; flex:auto; flex-direction:column;"; const view_config = document.createElement("select"); view_config.style.cssText = "font-size: 14px; margin-top:1em; margin-right:1em;"; view_config.innerHTML = `<option>削除した枠を:詰める</option><option>削除した枠を:詰めない</option>`; const enable_keyword_search = document.createElement("select"); enable_keyword_search.style.cssText = "font-size: 14px; margin-top:1em; margin-right:1em;"; enable_keyword_search.innerHTML = `<option>キーワード・定点観測時:無効</option><option>キーワード・定点観測時:有効</option>`; const id_name_cache_duration = document.createElement("select"); id_name_cache_duration.style.cssText = "font-size: 14px; margin-top:1em; margin-right:1em;"; id_name_cache_duration.innerHTML = `<option>ID-名前キャッシュ期間:3ヶ月間</option> <option>ID-名前キャッシュ期間:7日間</option> <option>ID-名前キャッシュ期間:1年間</option> <option>ID-名前キャッシュ期間:無効</option>`; const clear_id_name_cache_button = document.createElement("input"); clear_id_name_cache_button.style.cssText = "font-size:14px; margin-top:1em; margin-bottom:1em; margin-right:1em;"; clear_id_name_cache_button.type = "button"; clear_id_name_cache_button.value = "ID-名前キャッシュをクリア"; const ng_add_delete_buttons = document.createElement("div"); ng_add_delete_buttons.style.cssText = "display:flex; flex-direction:row;"; const ng_add_button = document.createElement("input"); ng_add_button.style.cssText = "font-size:18px; width:4em; margin-top:2em; margin-bottom: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-left:2em; margin-top:2em; margin-bottom:1em;"; ng_delete_button.type = "button"; ng_delete_button.value = "削除"; const ng_import_export_buttons = document.createElement("div"); ng_import_export_buttons.style.cssText = "display:flex; flex-direction:row;"; const ng_import_button = document.createElement("input"); ng_import_button.style.cssText = "font-size:14px; padding:0.5em; margin-bottom:1em;"; ng_import_button.type = "button"; ng_import_button.value = "インポート"; const ng_export_button = document.createElement("input"); ng_export_button.style.cssText = "font-size:14px; padding:0.5em; margin-left:2em; margin-bottom:1em;"; ng_export_button.type = "button"; ng_export_button.value = "エクスポート"; const exception_url_button = document.createElement("input"); exception_url_button.id = "exception_url_button"; exception_url_button.type = "button"; exception_url_button.value = "動作対象外のURLを設定する"; exception_url_button.style.cssText = "background-color:slateBlue; padding-left:0.5em; padding-right:0.5em; padding-top:1px; padding-bottom:1px; font-size:12px; margin-left:1em;"; const exception_dialog = document.createElement("div"); exception_dialog.id = "exception_dialog"; exception_dialog.style.cssText = "margin-bottom:1em; position:fixed; width:40em; height:40%; line-height:1.5em; display:none; flex-direction:column; background-color:gray; z-index:11"; const exception_caption = document.createElement("div"); exception_caption.innerHTML = "動作対象外のURLを一行ずつ設定する<br>(Javascryptの正規表現が可能)"; exception_caption.style.cssText = "margin-top:0.5em; margin-bottom:0.5em; margin-left:1em; font-size:14px; font-color:black;"; const exception_text = document.createElement("textarea"); exception_text.style.cssText = "margin-left:1em; margin-right:1em; margin-bottom:0.5; height:100%;"; const exception_close_button = document.createElement("input"); exception_close_button.type = "button"; exception_close_button.style.cssText = "font-size:18px; margin-top:0.5em; margin-bottom:0.5em; margin-left:1em; width:10em; padding-left:0.5em; padding-right:0.5em;"; exception_close_button.value = "保存して閉じる"; exception_close_button.onclick = function () { view_config_db.exceptions = exception_text.value; saveViewConfig(); location.reload(); exception_dialog.style.display = "none"; } ng_dialog_top.appendChild(ng_types); ng_dialog_top.appendChild(ng_durations); ng_dialog_top.appendChild(ng_close_button); ng_dialog_top.appendChild(ng_onoff_button); ng_dialog.appendChild(ng_dialog_top); ng_dialog_middle.appendChild(ng_list); ng_operation_area.appendChild(view_config); ng_operation_area.appendChild(enable_keyword_search); ng_operation_area.appendChild(id_name_cache_duration); ng_operation_area.appendChild(clear_id_name_cache_button); ng_operation_area.appendChild(ng_add_delete_buttons); ng_add_delete_buttons.appendChild(ng_add_button); ng_add_delete_buttons.appendChild(ng_delete_button); ng_operation_area.appendChild(ng_import_export_buttons); ng_import_export_buttons.appendChild(ng_import_button); ng_import_export_buttons.appendChild(ng_export_button); ng_dialog_middle.appendChild(ng_operation_area); ng_dialog.appendChild(ng_dialog_middle); parent_element.appendChild(ng_dialog); exception_dialog.appendChild(exception_caption); exception_dialog.appendChild(exception_text); exception_dialog.appendChild(exception_close_button); parent_element.appendChild(exception_dialog); parent_element.appendChild(exception_url_button); var ng_list_db = []; var id_name_list = []; var id_query_flag = 0; var view_config_db = {}; var id_name_cache_db = {}; var illust_id_cache_db = {}; loadViewConfig(); loadIdNameCache(); loadNgData(); updateNgList(); loadIllustIdCache(); ng_config_button.onclick = function(){ ng_dialog.style.display = "flex"; }; exception_url_button.onclick = function(){ exception_dialog.style.display = "flex"; }; ng_add_button.onclick = function(){ var ng_target = 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_target); var ng_info = { user : ng_target, 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_target); if (ng_user_name == null) { alert("指定されたIDに該当するユーザ名を取得できず"); return; } var id_name_obj = { id : ng_target, 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(); }; ng_import_button.onclick = function(){ var open_dlg = document.createElement("input"); open_dlg.type = "file"; open_dlg.onchange = (e) => { var reader = new FileReader(); reader.onload = () => { var obj = JSON.parse(reader.result); ng_list_db = obj.ng_list_db; view_config_db = obj.view_config_db; saveNgData(); saveViewConfig(); location.reload(); } reader.readAsText(e.target.files[0]); }; open_dlg.click(); }; ng_export_button.onclick = function(){ var a = document.createElement("a"); var blob = new Blob([JSON.stringify({ng_list_db, view_config_db})], {type: "text/plain"}); a.href = URL.createObjectURL(blob); a.download = "nicovideo_seiga_ng.config"; a.style.display = "none"; document.body.appendChild(a); a.click(); document.body.removeChild(a); }; ng_onoff_button.onclick = function () { if (ng_onoff_button.value == "一時停止"){ ng_onoff_button.value = "再開"; ng_config_button.value = "静画NG設定 --一時停止中--"; ng_config_button.style.backgroundColor = "slategray"; }else{ ng_onoff_button.value = "一時停止"; ng_config_button.value = "静画NG設定 --作動中--"; ng_config_button.style.backgroundColor = "red"; } view_config_db.state = ng_config_button.value; saveViewConfig(); location.reload(); } view_config.onchange = function(){ view_config_db.ng_item_filling =view_config.value; saveViewConfig(); } clear_id_name_cache_button.onclick = function(){ id_name_cache_db = null; saveIdNameChache(); } enable_keyword_search.onchange = function(){ view_config_db.at_keyword_search = enable_keyword_search.value; saveViewConfig(); } id_name_cache_duration.onchange = function(){ view_config_db.id_name_cache_duration = id_name_cache_duration.value; saveViewConfig(); } 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] - 1, yy_mm_dd[2]); if (today > end_date){ ng_list_db.splice(i, 1); } } if (isExceptionURL() == false){ //ユーザ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 = (id_name_cache_duration.value == "ID-名前キャッシュ期間:無効") ? null : queryIdNameCache(ng_list_db[j].user); if (name == null){ name = getUserName(ng_list_db[j].user); pushIdNameCache(ng_list_db[j].user, name); } 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 loadViewConfig(){ //ブラウザに保存した表示設定をロード var db = localStorage.getItem("nicovideo_seiga_ng_view_config"); if (db == null){ view_config_db.ng_item_filling = "削除した枠を:詰める"; view_config_db.at_keyword_search = "キーワード・定点観測時:無効"; view_config_db.state = "静画NG設定 --作動中--"; view_config_db.exceptions = "\/seiga.nicovideo.jp\/seiga\/im\/\n" + "\/seiga.nicovideo.jp\/my\/clip\/"; view_config_db.id_name_cache_duration = "ID-名前キャッシュ期間:3ヶ月間" }else{ view_config_db = JSON.parse(db); if (view_config_db.ng_item_filling == null) view_config_db.ng_item_filling = "削除した枠を:詰める"; if (view_config_db.at_keyword_search == null) view_config_db.at_keyword_search = "キーワード・定点観測時:無効"; if (view_config_db.state == null) view_config_db.state = "静画NG設定 --作動中--"; if (view_config_db.exceptions == null){ view_config_db.exceptions = "\/seiga.nicovideo.jp\/my\/clip\/"; } if (view_config_db.id_name_cache_duration == null) view_config_db.id_name_cache_duration = "ID-名前キャッシュ期間:3ヶ月間"; } view_config.value = view_config_db.ng_item_filling; enable_keyword_search.value = view_config_db.at_keyword_search; ng_config_button.value = view_config_db.state; id_name_cache_duration.value = view_config_db.id_name_cache_duration; if (ng_config_button.value.match(/静画NG設定 --作動中--/)) { ng_config_button.style.backgroundColor = "red"; ng_onoff_button.value = "一時停止"; }else{ ng_config_button.style.backgroundColor = "slategray"; ng_onoff_button.value = "再開"; } exception_text.value = view_config_db.exceptions; if (isExceptionURL()) { ng_config_button.value += "[対象外URL]"; ng_config_button.style.backgroundColor = "slategray"; } if (isKeywordException()) { ng_config_button.value += "[キーワード停止中]"; ng_config_button.style.backgroundColor = "slategray"; } if (isStationaryMeasureException()) { ng_config_button.value += "[定点観測停止中]"; ng_config_button.style.backgroundColor = "slategray"; } } function saveViewConfig(){ //表示設定をブラウザに保存 localStorage.setItem("nicovideo_seiga_ng_view_config", JSON.stringify(view_config_db)); } function loadIdNameCache(){ //ユーザID・ユーザ名情報のキャッシュをロード var db = localStorage.getItem("nicovideo_seiga_ng_user_id_cache"); if (db == null){ id_name_cache_db = { items:[] }; return; }else{ id_name_cache_db = JSON.parse(db); if (id_name_cache_db == null){ id_name_cache_db = { items:[] }; return; } } //有効期限切れのユーザID・ユーザ名情報があったら削除 if (view_config_db.id_name_cache_duration != "ID-名前キャッシュ期間:無効"){ var days_msec; if (id_name_cache_duration == "ID-名前キャッシュ期間:3ヶ月間") days_msec = 90 * 8640000; else if (id_name_cache_duration == "ID-名前キャッシュ期間:7日間") days_msec = 7 * 8640000; else if (id_name_cache_duration == "ID-名前キャッシュ期間:1年間") days_msec = 365 * 8640000; var today = new Date(); for (var i = id_name_cache_db.items.length - 1; i >= 0; i--){ var yy_mm_dd = id_name_cache_db.items[i].date.split("/"); var registered_date = new Date(yy_mm_dd[0], yy_mm_dd[1] - 1, yy_mm_dd[2]); if ((today.getTime() - registered_date.getTime()) > days_msec) id_name_cache_db.items.splice(i, 1); } } } function pushIdNameCache(user_id, user_name){ //ユーザIDとユーザ名の組み合わせをキャッシュに追加(5000件まで) var MAX = 5000; var obj = { user_id: user_id, user_name: user_name, date: dateString(new Date())} for (var i = 0; i < id_name_cache_db.items.length; i++){ //既に登録済みのユーザIDなら更新してリターン if (id_name_cache_db.items[i].user_id == user_id){ id_name_cache_db.items[i].user_name = obj.user_name; id_name_cache_db.items[i].date = obj.date; return; } } if (id_name_cache_db.items.length < MAX){ //新規追加 id_name_cache_db.items.push(obj); }else{ //一番古いレコードを上書きして追加 id_name_cache_db.items.splice(0, 1); id_name_cache_db.items.push(obj); } } function saveIdNameChache(){ //ユーザID・ユーザ名情報のキャッシュをブラウザに保存 localStorage.setItem("nicovideo_seiga_ng_user_id_cache", JSON.stringify(id_name_cache_db)); } function queryIdNameCache(user_id){ for (var i = 0; i < id_name_cache_db.items.length; i++){ if (id_name_cache_db.items[i].user_id == user_id) return id_name_cache_db.items[i].user_name; } return null; } function pushIllustIdCache(illust_id, user_id){ //静画IDと投稿者の組み合わせを循環配列キャッシュに追加(5000件まで) var CYCLE_MAX = 5000; for (var i = 0; i < illust_id_cache_db.items.length; i++){ //既に登録済みの静画IDならリターン if (illust_id_cache_db.items[i].illust_id == illust_id) return; } illust_id_cache_db.cycle_idx = (illust_id_cache_db.cycle_idx++) % CYCLE_MAX; if (illust_id_cache_db.items[illust_id_cache_db.cycle_idx] == null){ //新規追加 illust_id_cache_db.items.push({ illust_id: illust_id, user_id: user_id}); }else{ //一番古いレコードを上書きして追加 illust_id_cache_db.items[illust_id_cache_db.cycle_idx].illust_id = illust_id; illust_id_cache_db.items[illust_id_cache_db.cycle_idx].user_id = user_id; } } function loadIllustIdCache(){ //静画IDと投稿者のキャッシュをロード var db = localStorage.getItem("nicovideo_seiga_ng_illust_cache"); if (db == null){ illust_id_cache_db = { cycle_idx:-1, items:[]}; }else{ illust_id_cache_db = JSON.parse(db); } } function saveIllustIdChache(){ //静画IDと投稿者のキャッシュをブラウザに保存 localStorage.setItem("nicovideo_seiga_ng_illust_cache", JSON.stringify(illust_id_cache_db)); } function isExceptionURL(){ if (view_config_db.exceptions == null) return false; var ex = view_config_db.exceptions.split("\n"); for (var j = ex.length - 1; j >= 0; j--) if (ex[j] == "") ex.splice(j, 1); for (var i = 0; i < ex.length; i++){ var ex2 = ex[i]; if (ex[i].startsWith("/")) ex2 = ex[i].substr(1); if (ex2.endsWith("/")) ex2 = ex2.substr(0, ex2.length - 1); var regex = new RegExp(ex2, "ig"); if (location.href.match(regex)){ return true; } } return false; } function isKeywordException(){ if(view_config_db.at_keyword_search != "キーワード・定点観測時:無効") return false; return (mode == "キーワード検索"); } function isStationaryMeasureException(){ if(view_config_db.at_keyword_search != "キーワード・定点観測時:無効") return false; return (mode == "定点観測"); } 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){ let xhr = new XMLHttpRequest(); xhr.onreadystatechange = function (){ if(xhr.readyState == 4){ if(xhr.status == 0) alert("XHR 通信失敗"); else{ if((200 <= xhr.status && xhr.status < 300) || (xhr.status == 304)); else alert("その他の応答:" + xhr.status); } } }; xhr.open("GET", url, false); xhr.send(null); var resp = xhr.responseXML; xhr.abort(); return resp; } function getUserName(id){ var username_query_url = "https://seiga.nicovideo.jp/api/user/info?id=" + id; var xml = requestXml(username_query_url); if (xml == null) return null; var nickname = xml.documentElement.getElementsByTagName("nickname")[0]; if (nickname == null) return null; return nickname.textContent; } function getIllustInfo(id){ var illustinfo_query_url = "https://seiga.nicovideo.jp/api/illust/info?id=" + id; var xml = requestXml(illustinfo_query_url); var title = xml.documentElement.getElementsByTagName("title")[0]; var user_id = xml.documentElement.getElementsByTagName("user_id")[0]; return {title: (title != null) ? title.textContent : null, user_id: (user_id != null) ? user_id.textContent : null}; } function checkNgItem(user_names, user_ids, illust_ids, illust_tags){ var matched = []; for (var idx = 0; idx < user_names.length; idx++){ //NGリストから1件ずつ該非をチェック for (var i = 0; i < ng_list_db.length; i++){ if (ng_list_db[i].type == "NGユーザー名") { //NGユーザ名での判定 if (user_names[idx] != null){ //投稿のユーザ名が与えられている場合 if (user_names[idx] == ng_list_db[i].user) matched.push(illust_tags[idx]); }else{ //投稿のユーザ名が与えられていない場合 if (user_ids[idx] == null) { user_ids[idx] = getIllustInfo(illust_ids[idx]).user_id; pushIllustIdCache(illust_ids[idx], user_ids[idx]); } user_names[idx] = getUserName(user_ids[idx]); pushIdNameCache(user_ids[idx], user_names[idx]); if (user_names[idx] == ng_list_db[i].user) matched.push(illust_tags[idx]); } }else if(ng_list_db[i].type == "NGユーザーID"){ //NGユーザIDでの判定 if (user_ids[idx] != null){ //投稿のユーザIDが与えられている場合 if (user_ids[idx] == ng_list_db[i].user) matched.push(illust_tags[idx]); }else if (user_names[idx] != null){ //投稿のユーザIDの代わりにユーザ名が与えられている場合 for (var j = 0; j < id_name_list.length; j++){ //NGユーザID→ユーザ名変換リストを検索 if (user_names[idx] == id_name_list[j].name){ //ユーザ名は一致したが同名の別人の可能性があるので、 //静画IDがある場合は、努力範囲でユーザIDを問い合わせる。 if (illust_ids[idx] != null){ var info = getIllustInfo(illust_ids[idx]); pushIllustIdCache(illust_ids[idx], info.user_id); if ((info == null) || (info.user_id == null)) matched.push(illust_tags[idx]); if (info.user_id == ng_list_db[i].user) matched.push(illust_tags[idx]); } else matched.push(illust_tags[idx]); } } }else if (illust_ids[idx] != null){ //投稿ユーザIDも投稿ユーザ名も無いが、投稿静画IDが与えられている場合 var info2 = getIllustInfo(illust_ids[idx]); pushIllustIdCache(illust_ids[idx], info2.user_id); user_ids[idx] = info2.user_id; if (user_ids[idx] == ng_list_db[i].user) matched.push(illust_tags[idx]); } }else if(ng_list_db[i].type == "NG静画ID"){ //NG静画IDでの判定 if (illust_ids[idx] != null) { if (illust_ids[idx].replace("im", "") == ng_list_db[i].user.replace("im", "")) matched.push(illust_tags[idx]); } } } } return matched; } function parseAndCheckNgItems(mode){ var ngElement, illust_tags, illust_ids, user_names, user_ids; if(isKeywordException() || isStationaryMeasureException()) return []; var info = getTagsIdsNames(mode); illust_tags = info.tags; illust_ids = info.iids; user_names = info.names; user_ids = info.uids; return checkNgItem(user_names, user_ids, illust_ids, illust_tags); } function getTagsIdsNames(mode){ var inner_tags, illust_tags, illust_ids, user_names, user_ids; var getCenterImgInnerTags = () => Array.prototype.slice.call(document.getElementsByClassName("center_img_inner ")); var getUserTags = () => Array.prototype.slice.call(document.getElementsByClassName('user')).filter(elm => (elm.getAttribute("data-bind") == null)).filter(elm2 => (elm2.getAttribute("data-id") == null)); var getIdsFromMiddle = (tags) => tags.map(elem => elem.href.substring("https://seiga.nicovideo.jp/seiga/im".length, elem.href.indexOf("?"))); var getIdsFromLast = (tags) => tags.map(elem => elem.href.substr(elem.href.indexOf("/seiga/im") + ("/seiga/im").length)); var get2ndAncestor = (tags) => tags.map(elem => elem.parentNode.parentNode); var get3rdAncestor = (tags) => tags.map(elem => elem.parentNode.parentNode.parentNode); var getUserNamesEmpty = (tags) => tags.map(elem => null); var getUserNames = (tags) => tags.map(elem => elem.innerHTML); var getUserNamesRanking = (tags) => tags.map(elem => { var elem2 = elem.getElementsByClassName("rank_txt_user"); return (elem2.length > 0) ? elem2[0].children[0].textContent : null; }); var getUserIdsEmpty = (tags) => tags.map(elem => null); var getUserIdsRanking = (tags) => tags.map(elem => { var elem2 = elem.getElementsByClassName("rank_txt_user"); return (elem2.length > 0) ? elem2[0].children[0].href.substr(elem2[0].children[0].href.lastIndexOf("/") + 1) : null; }); if (mode == "キーワード検索"){ inner_tags = getCenterImgInnerTags(); illust_ids = getIdsFromMiddle(inner_tags); illust_tags = get2ndAncestor(inner_tags); user_names = getUserNamesEmpty(illust_tags); user_ids = getUserIdsEmpty(illust_tags); } else if (mode == "ランキング・まとめ"){ inner_tags = getCenterImgInnerTags(); illust_ids = getIdsFromMiddle(inner_tags); illust_tags = get3rdAncestor(inner_tags); user_names = getUserNamesRanking(illust_tags); user_ids = getUserIdsRanking(illust_tags); } else if (mode == "ランキング・個別"){ inner_tags = getCenterImgInnerTags(); illust_ids = getIdsFromMiddle(inner_tags); illust_tags = get3rdAncestor(inner_tags); user_names = getUserNamesRanking(illust_tags); user_ids = getUserIdsRanking(illust_tags); } else if (mode == "定点観測") { inner_tags = getCenterImgInnerTags(); illust_ids = getIdsFromLast(inner_tags); illust_tags = get2ndAncestor(inner_tags); user_names = getUserNamesEmpty(illust_tags); user_ids = getUserIdsEmpty(illust_tags); } else if ((mode == "タグ検索") || (mode == "すべてのイラスト")) { inner_tags = getUserTags(); illust_ids = getIdsFromLast(get2ndAncestor(inner_tags)); illust_tags = get3rdAncestor(inner_tags); user_names = getUserNames(inner_tags); user_ids = getUserIdsEmpty(illust_tags); } else if (mode == "投稿ページ") { inner_tags = getUserTags(); illust_ids = getIdsFromLast(get2ndAncestor(inner_tags)); illust_tags = get3rdAncestor(inner_tags); user_names = getUserNames(inner_tags); user_ids = getUserIdsEmpty(illust_tags); } else if (mode == "トップページ") { inner_tags = getUserTags(); illust_ids = getIdsFromLast(get2ndAncestor(inner_tags)); illust_tags = get3rdAncestor(inner_tags); user_names = getUserNames(inner_tags); user_ids = getUserIdsEmpty(illust_tags); } //静画IDキャッシュからユーザIDを補完 for (var i = 0; i < illust_ids.length; i++){ if (user_ids[i] != null) continue; for (var j = 0; j < illust_id_cache_db.items.length; j++){ if (illust_id_cache_db.items[j].illust_id == illust_ids[i]) { user_ids[i] = illust_id_cache_db.items[j].user_id; } } } //有効になっている場合のみ、ユーザIDキャッシュからユーザ名を補完 if (id_name_cache_duration.value != "ID-名前キャッシュ期間:無効"){ for (var ii = 0; ii < user_ids.length; ii++){ if (user_names[ii] != null) continue; user_names[ii] = queryIdNameCache(user_ids[ii]); } } return { tags:illust_tags, iids:illust_ids, names:user_names, uids:user_ids }; } if (ng_config_button.value == "静画NG設定 --一時停止中--") return; if (isExceptionURL()) return; var matched_ng_items = parseAndCheckNgItems(mode); saveIdNameChache(); saveIllustIdChache(); for (i = matched_ng_items.length-1; i >= 0; i--){ if (mode.match(/ランキング/)){ //ランキングで詰める機能は未実装 matched_ng_items[i].style.visibility = 'hidden'; } else if (view_config.value == "削除した枠を:詰める"){ matched_ng_items[i].remove(); }else{ matched_ng_items[i].style.visibility = 'hidden'; } }