Greasy Fork

ニコニコ静画、クッキー☆連投荒らしNG

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

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

// ==UserScript==
// @name         ニコニコ静画、クッキー☆連投荒らしNG
// @namespace    http://tampermonkey.net/
// @version      0.514
// @description  申し訳ないが連投荒らしはNG
// @author       cbxm
// @match        https://seiga.nicovideo.jp/tag/%E3%82%AF%E3%83%83%E3%82%AD%E3%83%BC%E2%98%86*
// @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
                }
            };
            this.option = await this.optionStorage.GetStorageData(defaultOption);
            //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);
                    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();
                    });
                    div.addEventListener("click", e => this.ClickList(e.currentTarget));
                }
            }
        }
        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 span = document.createElement("span");
            span.id = "optionSpan";
            parent.appendChild(span);
            const button = document.createElement("input");
            button.type = "button";
            button.value = "クッキー☆連投NG";
            button.style.backgroundColor = "yellow";
            button.style.padding = "1px 5px";
            button.style.fontSize = "110%";
            button.style.cssText += "color: black !important;";
            button.addEventListener("click", () => dialog.style.visibility = (dialog.style.visibility == "hidden") ? "visible" : "hidden");
            span.appendChild(button);
            const dialog = document.createElement("div");
            dialog.style.backgroundColor = "white";
            dialog.style.visibility = "hidden";
            dialog.style.position = "absolute";
            dialog.style.padding = "5px";
            dialog.style.zIndex = "10";
            dialog.style.border = "2px solid";
            span.appendChild(dialog);
            const setJudgeRigorFlex = document.createElement("div");
            setJudgeRigorFlex.style.padding = "10px 10px";
            dialog.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 div1 = document.createElement("div");
            dialog.appendChild(div1);
            const list1 = document.createElement("div");
            list1.style.display = "flex";
            div1.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.margin = "3px";
            list1.appendChild(allSelect);
            allSelect.addEventListener("click", () => {
                const infos = Array.from(document.getElementsByClassName("userInfoItem"));
                for (let info of infos) {
                    this.ClickList(info);
                }
            });
            const list2 = document.createElement("div");
            list2.style.position = "relative";
            list2.style.display = "flex";
            div1.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);
            this.DrawList();
            for (let i = 1; i < Status.MAX; i++) {
                const div = document.createElement("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);
                buttonList.appendChild(div);
                toButton.addEventListener("click", async () => {
                    while (this.selectedList.length != 0) {
                        const element = this.selectedList.pop();
                        if (element != undefined) {
                            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 = "10px";
            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.marginTop = "10px";
            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 = "20px";
            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("click", async () => {
                if (illustInfo.user != undefined) {
                    illustInfo.user.status = Status.WHITE;
                    for (let info of this.illustInfos) {
                        if (info.user == illustInfo.user) {
                            info.element.getElementsByTagName("img")[0].style.filter = "brightness(1)";
                            const buttons = info.element.getElementsByClassName("toListButton");
                            while (buttons.length != 0) {
                                buttons[0].remove();
                            }
                        }
                    }
                    this.DrawList();
                    await this.cacheStorage.SetStorageData(this.cache);
                }
            });
            blackButton.addEventListener("click", async () => {
                if (illustInfo.user != undefined) {
                    illustInfo.user.status = Status.BLACK;
                    for (let info of this.illustInfos) {
                        if (info.user == illustInfo.user) {
                            info.element.remove();
                        }
                    }
                    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) {
                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);
                }
                user.illusts.push(result.illusts[i]);
                unkownInfos[i].user = user;
            }
            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);
            this.SetOptionButton();
            //消すもしくは最後尾に暗くして追加
            for (let info of this.illustInfos) {
                this.UpdateIllust(info);
            }
        }
    }
    ;
    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