Narou Ranking NG safari mobile

小説家になろうランキングでのNGフィルタリング機能

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         Narou Ranking NG safari mobile
// @description  小説家になろうランキングでのNGフィルタリング機能
// @author       rugafo
// @match        https://yomou.syosetu.com/rank/*
// @exclude      https://yomou.syosetu.com/rank/top/
// @grant        GM_addStyle
// @grant        GM_deleteValue
// @grant        GM_getValue
// @grant        GM_listValues
// @grant        GM_setValue
// @version      20240907
// @namespace    https://greasyfork.org/ja/scripts/454473
// ==/UserScript==

document.addEventListener("DOMContentLoaded",function(){
});

//console.log(GM_listValues())


// セーブデータ・読込キー
const NAROU_NG_IDS_KEY = 'narou_ng_ids';

// セーブデータ・ロード関数
function load_savedata(key) {
    const DATA = GM_getValue(key);
    return DATA ? DATA.split(' ') : [];// 良くない書き方?
}


// セーブデータ・セーブ関数
function save_savedata(key, array) {
    GM_setValue(key, array.join(' '));
}


function delete_savedata(key) {
    switch (key) {
        case NAROU_NG_IDS_KEY:
            if (window.confirm('NG小説IDを全削除しますか?')) {
                GM_deleteValue(key);
                window.alert('NG小説IDを全削除しました');
            }
            break;

        default:
            break;
    }
}


// ランキング内の小説をノードリストとして所得
/*var ranking_nodelist_n = document.querySelectorAll('ul.ranking > li.title');
var ranking_nodelist = [];
for (let i = 0; i < ranking_nodelist_n.length; i++) {
    ranking_nodelist[i] = ranking_nodelist_n[i].parentElement;
}
*/

var ranking_nodelist = document.querySelectorAll('div.p-ranklist-item__column');
//var ranked_id_arr = Array.from(document.querySelectorAll('ul.ranking > li.title :nth-child(2)') ,a => a.href.substring(26, 33));
var ranked_id_arr1 = Array.from(document.querySelectorAll('div.p-ranklist-item__title>a'))//> href.substring(26, 33));
var ranked_id_arr = [];
for (let i = 0; i < ranked_id_arr1.length; i++) {
    ranked_id_arr[i] = ranked_id_arr1[i].href.substring(26, 33);
}
//alert(ranking_nodelist.innerhtml)
//console.log(ranked_id_arr);

var myuto = document.querySelectorAll('p.u-text-empty');
for (let i = 0; i < myuto.length; i++) {
    myuto[i].parentElement.parentElement.classList.add('censored');
}
//console.log(myuto);
var ng_novel_ids_array = load_savedata(NAROU_NG_IDS_KEY);

// スクリプトでNG小説を隠すのに使うCSS要素を作成して追加
GM_addStyle('.censored { display: none; }');


function toggle(num) {
    //var target_classList = ranking_nodelist[num].childNodes[3].classList;
    var target_classList = ranking_nodelist[num].classList;
    var target_id = ranked_id_arr[num];
    if (target_classList.contains('censored')) {
        target_classList.remove('censored');
        ng_novel_ids_array = ng_novel_ids_array.filter(id => id != target_id);
    } else {
        target_classList.add('censored');
        var bar= ranking_nodelist[num].nextElementSibling;
        bar.classList.add('censored');
        // alert(bar.innerHTML);
        ng_novel_ids_array.push(target_id);

    }
    //console.log('NG小説ID一覧が更新されました。');
    //console.log(ng_novel_ids_array);
    save_savedata(NAROU_NG_IDS_KEY, ng_novel_ids_array);
}


// NG登録ボタンを↑のリスト個数分つくって配列に追加
var button_array = [];
for (let i = 0; i < ranking_nodelist.length; i++) {
    button_array[i] = document.createElement('button');
    button_array[i].innerText = '非表示';
    button_array[i].addEventListener('click', function () {
        toggle(i);

    });// ループ内関数宣言は駄目らしい? 動いているが…
    ranking_nodelist[i].firstElementChild.appendChild(button_array[i]);
}


// メイン部分。ここどうにかならないものか
// NG小説IDが見つかったとき
if (ng_novel_ids_array.length > 0) {
    //console.log('保存されたNG小説IDが見つかりました。');
    //console.log(ng_novel_ids_array.join(' '));
    let key_array = ng_novel_ids_array.slice();
    for (let i = 0; i < ranked_id_arr.length; i++) {
        for (let j = 0; j < key_array.length; j++) {

            let soeji = ranked_id_arr.indexOf(key_array[j]);
            if (soeji != -1) {
                //ranking_list_nodelist[soeji].lastElementChild.classList.add('censored');
                ranking_nodelist[soeji].classList.add('censored');
                var bar= ranking_nodelist[soeji].nextElementSibling
                bar.classList.add('censored');
                key_array.splice(j, 1);
            }
        }
    }
} else {
    //console.log('保存されたNG小説IDは見つかりませんでした。');
}


// フロートNGメニュー
GM_addStyle('.floated { position: fixed; right: 0; bottom: 0; }')

const FLOAT_NG_MENU = document.createElement('div');
FLOAT_NG_MENU.classList.add('floated');
document.body.appendChild(FLOAT_NG_MENU);
var bottontime=0;
const EXPRESS_SAVE_DATA_BUTTON = document.createElement('button');
EXPRESS_SAVE_DATA_BUTTON.innerText = 'NG一覧';
EXPRESS_SAVE_DATA_BUTTON.addEventListener('click', function () {
    //alert(load_savedata(NAROU_NG_IDS_KEY));
    if(bottontime == 0){
        bottontime = 1;
        var tear = document.createElement("textarea")
        tear.appendChild(document.createTextNode(load_savedata(NAROU_NG_IDS_KEY)));
        tear.id = "memoarea";
        tear.setAttribute("rows","4");
        tear.setAttribute("cols","40");
        document.body.insertBefore(tear,document.body.firstElementChild);

        var btn = document.createElement("input");
        btn.setAttribute("type","button");
        btn.setAttribute("value","保存");
        tear.parentElement.insertBefore(btn,tear.nextSibling);

        var tojiru = document.createElement("input");
        tojiru.setAttribute("type","button");
        tojiru.setAttribute("value","閉じる");
        btn.parentElement.insertBefore(tojiru,btn.nextSibling);

        btn.addEventListener('click', function () {
            var elem = document.getElementById('memoarea').value;
            //alert(ng_novel_ids_array);
            ng_novel_ids_array = elem.replaceAll(",",' ');
            //alert(ng_novel_ids_array);
            GM_setValue(NAROU_NG_IDS_KEY, ng_novel_ids_array);
            tear.parentElement.removeChild(tear);
            btn.parentElement.removeChild(btn);
            tojiru.parentElement.removeChild(tojiru);
            bottontime=0;
        });
        tojiru.addEventListener('click', function () {
            tear.parentElement.removeChild(tear);
            btn.parentElement.removeChild(btn);
            tojiru.parentElement.removeChild(tojiru);
            bottontime=0;
        });
    };

});
document.querySelector('.floated').appendChild(EXPRESS_SAVE_DATA_BUTTON);


const DELETE_SAVE_DATA_BUTTON = document.createElement('button');
DELETE_SAVE_DATA_BUTTON.innerText = 'NG全削除';
DELETE_SAVE_DATA_BUTTON.addEventListener('click', function () { delete_savedata(NAROU_NG_IDS_KEY); });
document.querySelector('.floated').appendChild(DELETE_SAVE_DATA_BUTTON);