Greasy Fork

ニコニコ静画、簡単NGスクリプト

申し訳ないが連投荒らしはNG

当前为 2020-10-20 提交的版本,查看 最新版本

// ==UserScript==
// @name         ニコニコ静画、簡単NGスクリプト
// @namespace    http://tampermonkey.net/
// @version      0.810
// @description  申し訳ないが連投荒らしはNG
// @author       cbxm
// @match        https://seiga.nicovideo.jp/tag/*
// @grant        GM.xmlHttpRequest
// @grant        GM.getValue
// @grant        GM.setValue
// @run-at document-start
// ==/UserScript==
(async () => {
    "use strict";
    ;
    ;
    class Util {
        //xmlString=未探査部分
        static XmlToObj(xmlString) {
            const F = (xmlString, obj) => {
                //タグを抜き出す
                let tagMatchs = null;
                while (true) {
                    tagMatchs = xmlString.match(/<([^>]+)>/);
                    //タグがないということはそれが値になる
                    if (tagMatchs == null) {
                        return xmlString;
                    }
                    if (tagMatchs[1][tagMatchs[1].length - 1] == "/") {
                        xmlString = xmlString.replace(/<[^>]+>([^]*)/, "$1");
                    }
                    else {
                        break;
                    }
                }
                const tag = tagMatchs[1];
                //タグの内側とその先を抜き出す
                const matchChildlen = [];
                while (true) {
                    const matchs = xmlString.match(new RegExp(`^[^<]*<${tag}>([^]+?)<\/${tag}>([^]*)`));
                    if (matchs == null) {
                        break;
                    }
                    matchChildlen.push(matchs[1]);
                    xmlString = matchs[2];
                }
                //タグあったのにマッチしなかったおかしい
                if (matchChildlen.length == 0) {
                    return obj;
                }
                //そのタグが一つしかないとき、オブジェクトになる
                if (matchChildlen.length == 1) {
                    //子を探す
                    obj[tag] = F(matchChildlen[0], {});
                }
                //そのタグが複数あるとき、配列になる
                if (matchChildlen.length > 1) {
                    obj = [];
                    for (let i = 0; i < matchChildlen.length; i++) {
                        //子を探す
                        obj[i] = F(matchChildlen[i], {});
                    }
                }
                //兄弟を探す
                F(xmlString, obj);
                return obj;
            };
            //初期化で<xml>を取り除く
            xmlString = xmlString.replace(/\s*<[^>]+>([^]+)/, "$1");
            return F(xmlString, {});
        }
        static HtmlToDocument(str) {
            const parser = new DOMParser();
            return parser.parseFromString(str, "text/html");
        }
        static HtmlToChildNodes(str) {
            return this.HtmlToDocument(str).body.childNodes;
        }
        static Wait(ms) {
            return new Promise(r => setTimeout(r, ms));
        }
    }
    ;
    class Fetcher {
        static GMFetchText(url) {
            return new Promise(r => {
                GM.xmlHttpRequest({
                    url: url,
                    method: "GET",
                    onload: (response) => {
                        r(response.responseText);
                    }
                });
            });
        }
        static async FetchIllustDatas(ids) {
            if (ids.length == 0) {
                return { illusts: [], userIds: [] };
            }
            const url = `http:\/\/seiga.nicovideo.jp/api/illust/info?id_list=${ids.join()}`;
            const res = await this.GMFetchText(url);
            const obj = Util.XmlToObj(res);
            const list = Array.isArray(obj.response.image_list) ? obj.response.image_list : [obj.response.image_list.image];
            const illusts = [];
            for (let i = 0; i < list.length; i++) {
                illusts[i] = {
                    id: list[i].id,
                    created: new Date(list[i].created)
                };
            }
            return {
                illusts: illusts,
                userIds: list.map(l => l.user_id)
            };
        }
        static async FetchUserName(userId) {
            const url = "http://seiga.nicovideo.jp/api/user/info?id=" + userId;
            const json = Util.XmlToObj(await this.GMFetchText(url));
            return json.response.user.nickname;
        }
        static async FetchUserId(illustId) {
            const url = "https://seiga.nicovideo.jp/api/illust/info?id=im" + illustId;
            const resultText = await this.GMFetchText(url);
            const json = Util.XmlToObj(resultText);
            return json.response.image.user_id;
        }
    }
    ;
    class Storage {
        constructor(storageName) {
            this.storageName = "";
            this.storageName = storageName;
        }
        async GetStorageData(defaultValue = null) {
            const text = await GM.getValue(this.storageName, null);
            return text != null ? JSON.parse(decodeURIComponent(text)) : defaultValue;
        }
        async SetStorageData(data) {
            await GM.setValue(this.storageName, encodeURIComponent(JSON.stringify(data)));
        }
    }
    ;
    class Observer {
        static Wait(predicate, parent = document, option = null) {
            return new Promise(r => {
                if (option == null) {
                    option = {
                        childList: true,
                        subtree: true
                    };
                }
                const mutationObserver = new MutationObserver((mrs) => {
                    if (predicate(mrs)) {
                        mutationObserver.disconnect();
                        r(mrs);
                        return;
                    }
                });
                mutationObserver.observe(parent, option);
            });
        }
        ;
        static WaitAddedNode(predicate, parent, option = null) {
            return new Promise(r => {
                if (option == null) {
                    option = {
                        childList: true,
                        subtree: true
                    };
                }
                const mutationObserver = new MutationObserver((mrs) => {
                    //console.log(document.head.innerHTML);
                    //console.log(document.body.innerHTML);
                    for (let node of mrs) {
                        node.addedNodes.forEach(added => {
                            //console.log(added);
                            if (predicate(added)) {
                                mutationObserver.disconnect();
                                r(added);
                                return;
                            }
                        });
                    }
                });
                mutationObserver.observe(parent, option);
            });
        }
        ;
        static async DefinitelyGetElementById(id, parent = document, option = null) {
            const e = document.getElementById(id);
            if (e != null) {
                return e;
            }
            return this.WaitAddedNode(e => e.id != null && e.id == id, parent, option);
        }
        //getElementsByClassNameをつかうけど単体なので注意
        static async DefinitelyGetElementByClassName(className, parent = document, option = null) {
            const e = document.getElementsByClassName(className)[0];
            if (e != null) {
                return e;
            }
            return this.WaitAddedNode(e => e.className != null && e.className == className, parent, option);
        }
        //getElementsByTagNameをつかうけど単体なので注意
        static async DefinitelyGetElementByTagName(tagName, parent = document, option = null) {
            tagName = tagName.toUpperCase();
            const e = document.getElementsByTagName(tagName)[0];
            if (e != null) {
                return e;
            }
            return this.WaitAddedNode(e => e.tagName != null && e.tagName == tagName, parent, option);
        }
    }
    ;
    //暫定OK、暫定荒らし、確定OK、確定荒らし
    //type Status = "OK" | "NG" | "LOK" | "LNG"
    let Status;
    (function (Status) {
        Status[Status["NONE"] = 0] = "NONE";
        Status[Status["OK"] = 1] = "OK";
        Status[Status["NG"] = 2] = "NG";
        Status[Status["WHITE"] = 3] = "WHITE";
        Status[Status["BLACK"] = 4] = "BLACK";
        Status[Status["MAX"] = 5] = "MAX";
    })(Status || (Status = {}));
    class Main {
        constructor() {
            this.cache = [];
            this.illustInfos = [];
            this.selectedList = [];
            this.cacheStorage = new Storage("NICONICO_RENTO_ARASI_NG_DATA_CACHE");
            this.optionStorage = new Storage("NICONICO_RENTO_ARASI_NG_OPTION_CACHE");
        }
        async GetStorageData() {
            this.cache = (await this.cacheStorage.GetStorageData([]))
                .map(c => {
                if (typeof c.status == "string") {
                    if (c.status == "LOK") {
                        c.status = Status.WHITE;
                    }
                    else if (c.status == "LNG") {
                        c.status = Status.BLACK;
                    }
                    else if (c.status == "OK") {
                        c.status = Status.OK;
                    }
                    else if (c.status == "NG") {
                        c.status = Status.NG;
                    }
                    else {
                        c.status = Status.OK;
                    }
                }
                return c;
            });
            //console.log(this.cache);
            const defaultOption = {
                judge: {
                    time: 1 * 60 * 60 * 1000,
                    postCount: 3
                },
                okCacheMax: 1000 //どのくらいがいいのかわからない
            };
            this.option = await this.optionStorage.GetStorageData(defaultOption);
            if (this.option.judge == undefined) {
                this.option.judge = defaultOption.judge;
            }
            if (this.option.judge.time == undefined) {
                this.option.judge.time = defaultOption.judge.time;
            }
            if (this.option.judge.postCount == undefined) {
                this.option.judge.postCount = defaultOption.judge.postCount;
            }
            if (this.option.okCacheMax == undefined) {
                this.option.okCacheMax = defaultOption.okCacheMax;
            }
            //console.log(this.option);
        }
        GetInfo(illustId) {
            for (let c of this.cache) {
                for (let illust of c.illusts) {
                    if (illust.id == illustId) {
                        return { user: c, illust: illust };
                    }
                }
            }
            return undefined;
        }
        ChackArasi(user) {
            if (user.illusts.length == 0 || user.status == Status.BLACK || user.status == Status.WHITE || user.status == Status.NG) {
                return;
            }
            for (let illust of user.illusts) {
                if (typeof illust.created == "string") {
                    illust.created = new Date(illust.created);
                }
            }
            //新しい順
            const sorted = user.illusts.sort((a, b) => b.created.getTime() - a.created.getTime());
            for (let i = 0; i < sorted.length; i++) {
                const currentDate = sorted[i].created;
                let j = i + 1;
                let postCount = 1;
                while (true) {
                    if (j >= sorted.length || currentDate.getTime() - sorted[j].created.getTime() > this.option.judge.time) {
                        break;
                    }
                    j++;
                    postCount++;
                }
                if (postCount >= this.option.judge.postCount) {
                    user.status = Status.NG;
                    return;
                }
            }
        }
        ;
        GetIllustIds(itemListElement) {
            //document.getElementsByClassName("item_list")[0]
            const illustIdElements = itemListElement.getElementsByTagName("a");
            const illustIds = [];
            for (let i = 0; i < illustIdElements.length; i++) {
                const idMatchs = illustIdElements[i].href.match(/im(\d+)/);
                if (idMatchs == null) {
                    continue;
                }
                const id = idMatchs[1];
                illustIds.push(id);
            }
            return illustIds;
        }
        DrawList() {
            const list = document.getElementById("scrollUL");
            const onlyCurrentPageCheckbox = document.getElementById("onlyCurrentPageCheckbox");
            const listStatusSelect = document.getElementById("listStatusSelect");
            if (list == undefined || onlyCurrentPageCheckbox == undefined || listStatusSelect == undefined) {
                return;
            }
            const status = Status[listStatusSelect.value];
            list.innerHTML = "";
            for (let user of this.cache) {
                if (user.status == status) {
                    const info = this.illustInfos.find(info => info.user == user);
                    let sampleIllustId = info != undefined ? info.illustId : undefined;
                    if (onlyCurrentPageCheckbox.checked && sampleIllustId == undefined) {
                        continue;
                    }
                    if (sampleIllustId == undefined) {
                        sampleIllustId = user.illusts[0].id;
                    }
                    const div = document.createElement("div");
                    div.style.height = "70px";
                    div.style.display = "flex";
                    div.style.flexDirection = "column";
                    div.className = "userInfoItem";
                    list.appendChild(div);
                    div.addEventListener("click", e => this.ClickList(e.currentTarget));
                    {
                        const nameIdDiv = document.createElement("div");
                        nameIdDiv.style.top = "relative";
                        nameIdDiv.style.position = "4px";
                        div.appendChild(nameIdDiv);
                        {
                            const nameSpan = document.createElement("span");
                            nameSpan.className = "userName";
                            nameSpan.textContent = info == undefined ? "" : info.name;
                            nameSpan.style.fontSize = "130%";
                            nameSpan.style.color = "black";
                            nameSpan.style.width = "66px";
                            nameSpan.style.height = "24px";
                            nameSpan.style.padding = "3px";
                            nameIdDiv.appendChild(nameSpan);
                            const idSpan = document.createElement("span");
                            idSpan.className = "userId";
                            idSpan.textContent = user.userId;
                            idSpan.style.fontSize = "130%";
                            idSpan.style.color = "black";
                            idSpan.style.width = "66px";
                            idSpan.style.padding = "3px";
                            nameIdDiv.appendChild(idSpan);
                        }
                        const userAndSampleImgDiv = document.createElement("div");
                        div.appendChild(userAndSampleImgDiv);
                        {
                            const aUser = document.createElement("a");
                            aUser.href = `https:\/\/seiga.nicovideo.jp/user/illust/${user.userId}`;
                            userAndSampleImgDiv.appendChild(aUser);
                            {
                                const imgUser = document.createElement("img");
                                imgUser.src = `https:\/\/secure-dcdn.cdn.nimg.jp/nicoaccount/usericon/${Math.floor(parseInt(user.userId) / 10000)}/${user.userId}.jpg`;
                                imgUser.style.height = "40px";
                                imgUser.style.position = "relative";
                                imgUser.style.padding = "0 20px 0 10px";
                                imgUser.style.top = "-5px";
                                aUser.appendChild(imgUser);
                                imgUser.addEventListener("error", () => {
                                    imgUser.src = "https:\/\/secure-dcdn.cdn.nimg.jp/nicoaccount/usericon/defaults/blank.jpg";
                                });
                            }
                            const aSample = document.createElement("a");
                            aSample.href = `https:/\/seiga.nicovideo.jp/seiga/im${sampleIllustId}`;
                            userAndSampleImgDiv.appendChild(aSample);
                            {
                                const imgSample = document.createElement("img");
                                imgSample.src = `https:\/\/lohas.nicoseiga.jp\/\/thumb/${sampleIllustId}c`;
                                imgSample.style.height = "30px";
                                imgSample.style.position = "relative";
                                imgSample.style.top = "-5px";
                                aSample.appendChild(imgSample);
                                const bigSample = document.createElement("img");
                                bigSample.src = `https:\/\/lohas.nicoseiga.jp\/\/thumb/${sampleIllustId}c`;
                                bigSample.style.height = "100px";
                                bigSample.style.pointerEvents = "none";
                                bigSample.style.position = "absolute";
                                bigSample.style.zIndex = "10";
                                imgSample.addEventListener("mouseover", () => {
                                    const clientRect = imgSample.getBoundingClientRect();
                                    const x = window.pageXOffset + clientRect.left + imgSample.width / 2 - 50;
                                    const y = window.pageYOffset + clientRect.top + imgSample.height / 2 - 50;
                                    bigSample.style.top = y + "px";
                                    bigSample.style.left = x + "px";
                                    document.body.appendChild(bigSample);
                                });
                                imgSample.addEventListener("mouseleave", () => {
                                    bigSample.remove();
                                });
                            }
                        }
                    }
                }
            }
        }
        ClickList(target) {
            if (target != null) {
                if (this.selectedList.includes(target)) {
                    target.style.backgroundColor = "";
                    this.selectedList = this.selectedList.filter(s => s != target);
                }
                else {
                    target.style.backgroundColor = "rgba(0, 140, 255, 0.5)";
                    this.selectedList.push(target);
                }
            }
        }
        async SetOptionButton() {
            const parent = await Observer.DefinitelyGetElementByClassName("sg_pankuzu");
            if (document.getElementById("optionSpan") != null) {
                return;
            }
            const optionSpan = document.createElement("span");
            optionSpan.id = "optionSpan";
            optionSpan.style.margin = "0 10px";
            parent.appendChild(optionSpan);
            {
                const optionButton = document.createElement("input");
                optionButton.type = "button";
                optionButton.value = "簡単NGスクリプト";
                optionButton.style.backgroundColor = "yellow";
                optionButton.style.padding = "1px 10px";
                optionButton.style.fontSize = "110%";
                optionButton.style.cssText += "color: black !important;";
                optionButton.addEventListener("click", () => {
                    optionDialog.style.display = (optionDialog.style.display == "none") ? "block" : "none";
                });
                optionSpan.appendChild(optionButton);
                const optionDialog = document.createElement("div");
                optionDialog.style.backgroundColor = "white";
                optionDialog.style.display = "none";
                optionDialog.style.position = "absolute";
                optionDialog.style.padding = "5px";
                optionDialog.style.marginLeft = "10px";
                optionDialog.style.zIndex = "10";
                optionDialog.style.border = "2px solid";
                optionSpan.appendChild(optionDialog);
                {
                    const setJudgeRigorFlex = document.createElement("div");
                    setJudgeRigorFlex.style.padding = "10px 10px 5px 10px";
                    optionDialog.appendChild(setJudgeRigorFlex);
                    {
                        const setJudgeTime = document.createElement("input");
                        setJudgeTime.type = "time";
                        setJudgeTime.style.height = "20px";
                        setJudgeTime.style.fontSize = "120%";
                        const hour = ('00' + Math.floor(this.option.judge.time / 60 / 1000 / 60).toString()).slice(-2);
                        const minutes = ('00' + (this.option.judge.time / 60 / 1000 % 60).toString()).slice(-2);
                        setJudgeTime.value = `${hour}:${minutes}`;
                        setJudgeTime.addEventListener("change", async () => {
                            const [h, m] = setJudgeTime.value.split(":").map(s => parseInt(s));
                            const ms = ((h * 60) + m) * 60 * 1000;
                            if (ms >= 1) {
                                this.option.judge.time = ms;
                                await this.optionStorage.SetStorageData(this.option);
                            }
                            else {
                                const hour = ('00' + Math.floor(this.option.judge.time / 60 / 1000 / 60).toString()).slice(-2);
                                const minutes = ('00' + (this.option.judge.time / 60 / 1000 % 60).toString()).slice(-2);
                                setJudgeTime.value = `${hour}:${minutes}`;
                            }
                        });
                        setJudgeRigorFlex.appendChild(setJudgeTime);
                        const setJudgeText1 = document.createElement("span");
                        setJudgeText1.textContent = "以内に";
                        setJudgeText1.style.color = "black";
                        setJudgeText1.style.fontSize = "15px";
                        setJudgeRigorFlex.appendChild(setJudgeText1);
                        const setJudgePostCount = document.createElement("input");
                        setJudgePostCount.type = "number";
                        setJudgePostCount.value = this.option.judge.postCount.toString();
                        setJudgePostCount.style.width = "40px";
                        setJudgePostCount.min = "2";
                        setJudgePostCount.style.height = "20px";
                        setJudgePostCount.style.fontSize = "120%";
                        setJudgePostCount.addEventListener("change", async () => {
                            const num = parseInt(setJudgePostCount.value);
                            if (num >= 2) {
                                this.option.judge.postCount = num;
                                await this.optionStorage.SetStorageData(this.option);
                            }
                            else {
                                this.option.judge.postCount = 2;
                                setJudgePostCount.value = this.option.judge.postCount.toString();
                            }
                        });
                        setJudgeRigorFlex.appendChild(setJudgePostCount);
                        const setJudgeText2 = document.createElement("span");
                        setJudgeText2.textContent = "回投稿で仮荒らし認定";
                        setJudgeText2.style.color = "black";
                        setJudgeText2.style.fontSize = "15px";
                        setJudgeRigorFlex.appendChild(setJudgeText2);
                    }
                    const list1 = document.createElement("div");
                    list1.style.display = "flex";
                    optionDialog.appendChild(list1);
                    {
                        const listStatusSelect = document.createElement("select");
                        listStatusSelect.id = "listStatusSelect";
                        listStatusSelect.style.margin = "5px";
                        list1.appendChild(listStatusSelect);
                        for (let i = 1; i < Status.MAX; i++) {
                            const option = document.createElement("option");
                            option.value = Status[i];
                            option.textContent = Status[i];
                            listStatusSelect.appendChild(option);
                        }
                        listStatusSelect.addEventListener("change", () => {
                            while (this.selectedList.length != 0) {
                                const element = this.selectedList.pop();
                                if (element != undefined) {
                                    element.style.backgroundColor = "";
                                }
                            }
                            this.DrawList();
                        });
                        const onlyCurrentPageCheckbox = document.createElement("input");
                        onlyCurrentPageCheckbox.type = "checkbox";
                        onlyCurrentPageCheckbox.id = "onlyCurrentPageCheckbox";
                        onlyCurrentPageCheckbox.checked = true;
                        onlyCurrentPageCheckbox.style.padding = "3px";
                        list1.appendChild(onlyCurrentPageCheckbox);
                        onlyCurrentPageCheckbox.addEventListener("change", () => this.DrawList());
                        const onlyCurrentPageLabel = document.createElement("label");
                        onlyCurrentPageLabel.htmlFor = "onlyCurrentPageCheckbox";
                        onlyCurrentPageLabel.textContent = "このページだけ";
                        onlyCurrentPageLabel.style.color = "black";
                        onlyCurrentPageLabel.style.padding = "3px";
                        list1.appendChild(onlyCurrentPageLabel);
                        const allSelect = document.createElement("input");
                        allSelect.type = "button";
                        allSelect.value = "全選択";
                        allSelect.style.color = "black";
                        allSelect.style.padding = "0 5px";
                        allSelect.style.margin = "3px";
                        list1.appendChild(allSelect);
                        allSelect.addEventListener("click", () => {
                            const infos = Array.from(document.getElementsByClassName("userInfoItem"));
                            for (let info of infos) {
                                this.ClickList(info);
                            }
                        });
                        const detailButton = document.createElement("input");
                        detailButton.type = "button";
                        detailButton.value = "詳細設定";
                        detailButton.style.color = "black";
                        detailButton.style.margin = "3px";
                        detailButton.style.marginLeft = "40px";
                        detailButton.style.padding = "0 5px";
                        list1.appendChild(detailButton);
                        detailButton.addEventListener("click", () => detailDialog.style.display = (detailDialog.style.display == "none") ? "block" : "none");
                        const detailDialog = document.createElement("div");
                        detailDialog.style.backgroundColor = "white";
                        detailDialog.style.display = "none";
                        detailDialog.style.position = "absolute";
                        detailDialog.style.padding = "10px";
                        detailDialog.style.zIndex = "10";
                        detailDialog.style.border = "2px solid";
                        detailDialog.style.left = "360px";
                        detailDialog.style.top = "50px";
                        list1.appendChild(detailDialog);
                        const setOKCacheMaxFlex = document.createElement("div");
                        detailDialog.appendChild(setOKCacheMaxFlex);
                        {
                            const setOKCacheMaxText1 = document.createElement("span");
                            setOKCacheMaxText1.textContent = "OKユーザーのキャッシュ最大数:";
                            setOKCacheMaxText1.style.color = "black";
                            setOKCacheMaxText1.style.fontSize = "15px";
                            setOKCacheMaxFlex.appendChild(setOKCacheMaxText1);
                            const setOKCacheMax = document.createElement("input");
                            setOKCacheMax.type = "number";
                            setOKCacheMax.value = this.option.okCacheMax.toString();
                            setOKCacheMax.style.width = "80px";
                            setOKCacheMax.min = "100";
                            setOKCacheMax.style.height = "20px";
                            setOKCacheMax.style.fontSize = "120%";
                            setOKCacheMax.addEventListener("change", async () => {
                                const num = parseInt(setOKCacheMax.value);
                                if (num >= 100) {
                                    this.option.okCacheMax = num;
                                    await this.optionStorage.SetStorageData(this.option);
                                }
                                else {
                                    this.option.okCacheMax = 100;
                                    setOKCacheMax.value = this.option.okCacheMax.toString();
                                }
                            });
                            setOKCacheMaxFlex.appendChild(setOKCacheMax);
                        }
                    }
                    const list2 = document.createElement("div");
                    list2.style.position = "relative";
                    list2.style.display = "flex";
                    optionDialog.appendChild(list2);
                    {
                        const userInfoList = document.createElement("ul");
                        userInfoList.id = "scrollUL";
                        userInfoList.style.overflowY = "scroll";
                        userInfoList.style.overflowX = "hidden";
                        userInfoList.style.height = "300px";
                        userInfoList.style.width = "250px";
                        list2.appendChild(userInfoList);
                        const buttonList = document.createElement("ul");
                        buttonList.style.width = "90px";
                        list2.appendChild(buttonList);
                        {
                            const moveButtonList = document.createElement("div");
                            moveButtonList.style.marginTop = "20px";
                            moveButtonList.style.marginBottom = "10px";
                            buttonList.appendChild(moveButtonList);
                            {
                                for (let i = 1; i < Status.MAX; i++) {
                                    const div = document.createElement("div");
                                    moveButtonList.appendChild(div);
                                    {
                                        const toButton = document.createElement("input");
                                        toButton.type = "button";
                                        toButton.style.padding = "3px";
                                        toButton.style.fontSize = "130%";
                                        toButton.style.margin = "3px";
                                        toButton.value = "→ " + Status[i];
                                        toButton.name = Status[i];
                                        div.appendChild(toButton);
                                        toButton.addEventListener("click", async () => {
                                            while (this.selectedList.length != 0) {
                                                const element = this.selectedList.pop();
                                                if (element == undefined) {
                                                    continue;
                                                }
                                                element.style.backgroundColor = "";
                                                const userId = element.getElementsByClassName("userId")[0].textContent;
                                                const user = this.cache.find(c => c.userId == userId);
                                                if (user != undefined) {
                                                    user.status = Status[toButton.name];
                                                }
                                            }
                                            for (let info of this.illustInfos) {
                                                this.UpdateIllust(info);
                                                this.DrawBlackWhiteButton(info);
                                            }
                                            this.DrawList();
                                            await this.cacheStorage.SetStorageData(this.cache);
                                        });
                                    }
                                }
                            }
                            const div = document.createElement("div");
                            buttonList.appendChild(div);
                            {
                                const selectedCacheClearButton = document.createElement("input");
                                selectedCacheClearButton.type = "button";
                                selectedCacheClearButton.style.padding = "3px";
                                selectedCacheClearButton.style.fontSize = "120%";
                                selectedCacheClearButton.style.margin = "3px";
                                selectedCacheClearButton.style.marginTop = "5px";
                                selectedCacheClearButton.style.backgroundColor = "yellow";
                                selectedCacheClearButton.style.cssText += "color: black !important";
                                selectedCacheClearButton.value = "→DELETE";
                                div.appendChild(selectedCacheClearButton);
                                selectedCacheClearButton.addEventListener("click", async () => {
                                    if (!window.confirm("選択したアイテムのキャッシュクリアしていいですか?\nホワイト・ブラックリストも削除されます。")) {
                                        return;
                                    }
                                    while (this.selectedList.length != 0) {
                                        const element = this.selectedList.pop();
                                        if (element != undefined) {
                                            const userId = element.getElementsByClassName("userId")[0].textContent;
                                            this.cache = this.cache.filter(c => c.userId != userId);
                                            const infos = this.illustInfos.filter(c => c.user != undefined && c.user.userId == userId);
                                            for (let info of infos) {
                                                if (info != undefined && info.user != undefined) {
                                                    info.user.status = Status.WHITE;
                                                    this.UpdateIllust(info);
                                                    this.DrawBlackWhiteButton(info);
                                                }
                                            }
                                            this.illustInfos = this.illustInfos.filter(c => c.user != undefined && c.user.userId != userId);
                                        }
                                    }
                                    this.DrawList();
                                    await this.cacheStorage.SetStorageData(this.cache);
                                });
                            }
                            const div2 = document.createElement("div");
                            buttonList.appendChild(div2);
                            {
                                const allCacheClearButton = document.createElement("input");
                                allCacheClearButton.type = "button";
                                allCacheClearButton.style.padding = "3px";
                                allCacheClearButton.style.fontSize = "120%";
                                allCacheClearButton.style.margin = "3px";
                                allCacheClearButton.style.backgroundColor = "red";
                                allCacheClearButton.value = "ALL\nDELETE";
                                div2.appendChild(allCacheClearButton);
                                allCacheClearButton.addEventListener("click", async () => {
                                    if (!window.confirm("全キャッシュクリアしていいですか?\nホワイト・ブラックリストも削除されます。")) {
                                        return;
                                    }
                                    for (let info of this.illustInfos) {
                                        if (info.user != undefined) {
                                            info.user.status = Status.WHITE;
                                            this.UpdateIllust(info);
                                            this.DrawBlackWhiteButton(info);
                                        }
                                    }
                                    this.illustInfos = [];
                                    this.cache = [];
                                    this.DrawList();
                                    await this.cacheStorage.SetStorageData(this.cache);
                                });
                            }
                            const div3 = document.createElement("div");
                            buttonList.appendChild(div3);
                            {
                                const reStartButton = document.createElement("input");
                                reStartButton.type = "button";
                                reStartButton.style.padding = "3px";
                                reStartButton.style.fontSize = "120%";
                                reStartButton.style.margin = "3px";
                                reStartButton.style.marginTop = "10px";
                                reStartButton.style.backgroundColor = "green";
                                reStartButton.style.cssText += "color: white !important";
                                reStartButton.value = "RE START";
                                div3.appendChild(reStartButton);
                                reStartButton.addEventListener("click", async () => {
                                    await this.Run();
                                    this.DrawList();
                                });
                            }
                        }
                    }
                }
            }
        }
        UpdateIllust(info) {
            if (info.user == undefined) {
                return;
            }
            if (info.user.status == Status.OK || info.user.status == Status.WHITE) {
                info.element.getElementsByTagName("img")[0].style.filter = "brightness(1)";
                if (info.element.parentElement == null) {
                    info.parent.appendChild(info.element);
                }
            }
            if (info.user.status == Status.NG) {
                info.element.getElementsByTagName("img")[0].style.filter = "brightness(0.3)";
                info.parent.appendChild(info.element);
            }
            if (info.user.status == Status.BLACK) {
                info.element.remove();
            }
        }
        DrawBlackWhiteButton(illustInfo) {
            if (illustInfo.user == undefined || illustInfo.user.status == Status.BLACK || illustInfo.user.status == Status.WHITE) {
                if (illustInfo.user != undefined && illustInfo.user.status == Status.WHITE) {
                    const list = Array.from(illustInfo.element.getElementsByClassName("toListButton"));
                    for (let l of list) {
                        l.remove();
                    }
                }
                return;
            }
            if (illustInfo.element.getElementsByClassName("toListButton").length > 0) {
                return;
            }
            const whiteButton = document.createElement("input");
            const blackButton = document.createElement("input");
            whiteButton.style.position = "relative";
            whiteButton.style.left = "110px";
            whiteButton.style.top = "-30px";
            whiteButton.style.width = "40px";
            whiteButton.style.height = "25px";
            whiteButton.style.visibility = "hidden";
            //上記のスタイルを両方に適用
            blackButton.style.cssText = whiteButton.style.cssText;
            whiteButton.type = "button";
            blackButton.type = "button";
            whiteButton.className = "toListButton";
            blackButton.className = "toListButton";
            whiteButton.name = "white";
            blackButton.name = "black";
            whiteButton.style.cssText += `background-color : white !important;`;
            blackButton.style.cssText += `background-color : black !important;`;
            whiteButton.style.left = "110px";
            blackButton.style.left = "115px";
            whiteButton.addEventListener("contextmenu", async (e) => {
                e.preventDefault();
                if (illustInfo.user == undefined) {
                    return;
                }
                illustInfo.user.status = Status.OK;
                for (let info of this.illustInfos) {
                    if (info.user != illustInfo.user) {
                        continue;
                    }
                    this.UpdateIllust(info);
                }
                this.DrawList();
                await this.cacheStorage.SetStorageData(this.cache);
            });
            whiteButton.addEventListener("click", async () => {
                if (illustInfo.user == undefined) {
                    return;
                }
                illustInfo.user.status = Status.WHITE;
                for (let info of this.illustInfos) {
                    if (info.user != illustInfo.user) {
                        continue;
                    }
                    this.UpdateIllust(info);
                    const buttons = info.element.getElementsByClassName("toListButton");
                    while (buttons.length != 0) {
                        buttons[0].remove();
                    }
                }
                this.DrawList();
                await this.cacheStorage.SetStorageData(this.cache);
            });
            blackButton.addEventListener("contextmenu", async (e) => {
                e.preventDefault();
                if (illustInfo.user == undefined) {
                    return;
                }
                illustInfo.user.status = Status.NG;
                for (let info of this.illustInfos) {
                    if (info.user != illustInfo.user) {
                        continue;
                    }
                    this.UpdateIllust(info);
                }
                this.DrawList();
                await this.cacheStorage.SetStorageData(this.cache);
            });
            blackButton.addEventListener("click", async () => {
                if (illustInfo.user == undefined) {
                    return;
                }
                illustInfo.user.status = Status.BLACK;
                for (let info of this.illustInfos) {
                    if (info.user != illustInfo.user) {
                        continue;
                    }
                    this.UpdateIllust(info);
                }
                this.DrawList();
                await this.cacheStorage.SetStorageData(this.cache);
            });
            illustInfo.element.addEventListener("mouseover", () => {
                blackButton.style.visibility = "visible";
                whiteButton.style.visibility = "visible";
            });
            illustInfo.element.addEventListener("mouseleave", () => {
                blackButton.style.visibility = "hidden";
                whiteButton.style.visibility = "hidden";
            });
            illustInfo.element.appendChild(whiteButton);
            illustInfo.element.appendChild(blackButton);
        }
        async AddInfos(illustListElement) {
            var _a;
            const illustElements = Array.from(illustListElement.getElementsByClassName("list_item"));
            const illustIds = this.GetIllustIds(illustListElement);
            const names = Array.from(illustListElement.getElementsByClassName("user"));
            //キャッシュからの情報と合わせて追加(もうこれ分かんねぇこともある)
            for (let i = 0; i < illustIds.length; i++) {
                if (this.illustInfos.some(info => info.illustId == illustIds[i])) {
                    continue;
                }
                const info = this.GetInfo(illustIds[i]);
                this.illustInfos.push({
                    name: (_a = names[i].textContent) !== null && _a !== void 0 ? _a : "",
                    illustId: illustIds[i],
                    illust: info == undefined ? undefined : info.illust,
                    user: info == undefined ? undefined : info.user,
                    element: illustElements[i],
                    parent: illustListElement
                });
            }
        }
        //メインクラス、メイン関数の肥大化もう始まってる!
        async Run(illustListElements) {
            await Observer.DefinitelyGetElementByClassName("illust_list");
            await Observer.DefinitelyGetElementById("footer");
            illustListElements = illustListElements !== null && illustListElements !== void 0 ? illustListElements : Array.from(document.getElementsByClassName("item_list"));
            for (let illustListElement of illustListElements) {
                illustListElement.style.visibility = "hidden";
                await this.AddInfos(illustListElement);
            }
            //console.log("infos", this.illustInfos);
            //これもう分かんねぇやつら
            const unkownInfos = this.illustInfos.filter(info => info.user == undefined);
            //この戻り値なんかダサい・・・ダサくない?
            const result = await Fetcher.FetchIllustDatas(unkownInfos.map(info => info.illustId));
            //これもう分かんねぇやつらとキャッシュまで!?の情報更新
            for (let i = 0; i < unkownInfos.length; i++) {
                unkownInfos[i].illust = result.illusts[i];
                let user = this.cache.find((c) => c.userId == result.userIds[i]);
                if (user == undefined) {
                    user = {
                        userId: result.userIds[i],
                        illusts: [],
                        status: Status.OK
                    };
                    this.cache.push(user);
                }
                else {
                    //キャッシュ使ったら後ろにしとく
                    this.cache = this.cache.filter(c => c != user);
                    this.cache.push(user);
                }
                user.illusts.push(result.illusts[i]);
                unkownInfos[i].user = user;
            }
            //増えすぎたキャッシュ削除
            if (this.cache.length > 0) {
                let okCount = 0;
                for (let c of this.cache) {
                    if (c.status == Status.OK) {
                        okCount++;
                    }
                }
                while (okCount > this.option.okCacheMax) {
                    //OK以外消さない
                    if (this.cache[0].status != Status.OK) {
                        const c = this.cache.shift();
                        this.cache.push(c);
                        continue;
                    }
                    //今使ってたら消さない
                    if (this.illustInfos.some(info => info.user == this.cache[0])) {
                        break;
                    }
                    this.cache.shift();
                    okCount--;
                }
            }
            //console.log(result);
            //ブラック,ホワイトリストにないイラストエレメントにボタン追加
            for (let illustInfo of this.illustInfos) {
                this.DrawBlackWhiteButton(illustInfo);
            }
            //情報取ってきた投稿者の荒らし判定更新 ↓これは重複排除
            for (let c of [...new Set(unkownInfos.map(u => u.user))]) {
                if (c != undefined) {
                    this.ChackArasi(c);
                }
            }
            await this.cacheStorage.SetStorageData(this.cache);
            await this.SetOptionButton();
            this.DrawList();
            for (let info of this.illustInfos) {
                this.UpdateIllust(info);
            }
            for (let illustListElement of illustListElements) {
                illustListElement.style.visibility = "visible";
            }
        }
    }
    ;
    const main = new Main();
    await main.GetStorageData();
    await main.Run();
    const illustList = await Observer.DefinitelyGetElementByClassName("illust_list");
    const mutationObserver = new MutationObserver(async (mrs) => {
        for (let mr of mrs) {
            for (let i = 0; i < mr.addedNodes.length; i++) {
                const element = mr.addedNodes[i];
                if (element.classList != null && element.classList.contains("item_list")) {
                    await main.Run([element]);
                }
            }
        }
    });
    mutationObserver.observe(illustList, {
        childList: true,
        subtree: true
    });
})();
//# sourceMappingURL=script.js.map