Web漫画アンテナ 既読対応

マイリストのページで既読漫画の背景色を変えます

< Web漫画アンテナ 既読対応 피드백

리뷰: 좋음 - 잘 동작함

§
작성: 2023-08-13

既読の色変が付かなくなった・保存されなくなったという現象がでましたが、
Cookieの容量が4KBを超えていたらしく、Cookie削除でまた正常動作するようになりました

§
작성: 2023-08-14

サイトを閉じる開くで消えなくなっていたので勘違いしてましたが
しばらく経つと消えてました

§
작성: 2023-08-14
수정: 2023-08-14

このスクリプトは3年前書きました。それ以来更新中止になりそうです。

このように書き直したら、修正できるはずです。

// ==UserScript==
// @name         Web漫画アンテナ 既読対応
// @namespace
// @description マイリストのページで既読漫画の背景色を変えます
// @version      0.20
// @author       kiyo
// @match        https://webcomics.jp/mylist
// @match        https://webcomics.jp/mylist*
// @grant        none
// @namespace 
// ==/UserScript==

(function () {
    let myStorage = null;
    try {
        myStorage = JSON.parse(localStorage._supportRead);
    } catch {
        myStorage = {};
    }
    if (!myStorage._VERSION_) {
        let newStorage = {};
        for (const [key, value] of Object.entries(myStorage)) {
            if (value && value.length >= 1 && value.unshift) newStorage[key] = value.filter(val => typeof val === 'string' && val.length === 8).map(val => +val).filter(val > 19691231)
        }
        myStorage._VERSION_ = 1;
        localStorage._supportRead = JSON.stringify(myStorage);
    }
    if (myStorage._VERSION_ !== 1) {
        console.error("エラーが発生しました - データベースのバージョンが正しくありません。");
        return;
    }
    const readColor = "#c5c5c6";
    const nowDate = new Date();

    const timeToMsec = (num, unit) => {
        // サイト内の時間表示が切り上げなので-1しておく(24時に更新した作品が時間により日付が前後してしまうのを回避)
        num = num - 1;
        switch (unit) {
            case "時間前":
                return num * 60 * 60 * 1000;
            case "分前":
                return num * 60 * 1000;
            case "秒前":
                return num * 1000;
            default:
                console.error(`timeToMsec Error: ${num}${unit}`);
        }
    }
    const dateToStr = (year, month, day) => `${year}${("0" + month).slice(-2)}${("0" + day).slice(-2)}`;
    const calcAgoDate = (nowDate, num, unit) => {
        let ago = timeToMsec(parseInt(num), unit);
        //console.log(ago, num, unit);
        const agoDate = new Date(nowDate - ago);
        const year = agoDate.getFullYear();
        const month = agoDate.getMonth() + 1;
        const day = agoDate.getDate();
        const result = dateToStr(year, month, day);
        if (typeof result !== 'string' || result.length !== 8) console.error("エラーが発生しました - 時間文字列の構文が正しくありません。")
        return result;
    }

    const entries = document.querySelectorAll(".entry");

    //function test(){console.log(this.i +","+ this.mangaId +","+ this.date);};
    function handleEvent() {
        let { i, mangaId, date } = this;
        date = +date;
        if (!(date > 19691231)) return;

        changeColor(entries[i], readColor);
        // 重複チェック&追加
        if (!(mangaId in myStorage)) {
            myStorage[mangaId] = [date];
        } else if (!(myStorage[mangaId].includes(date))) {
            myStorage[mangaId].push(date);
        }
        let jsonString = JSON.stringify(myStorage);

        let trialN = 4;
        // 4MB(4194304文字)以上になったら先頭から削除
        while (jsonString.length > 4194304 && trialN >= 1) {
            let arr = new Set();
            jsonString.replace(/\b\d{8}\b/g, (val) => {
                if (+val > 19691231 && +val < 29990101) {
                    arr.add(+val);
                }
            });
            arr = [...arr.values()].sort();
            let m = arr[Math.round(arr.length / 2)];
            for (const [key, value] of Object.entries(myStorage)) {
                if (value && value.length >= 1 && value.unshift) {
                    newStorage[key] = value.filter(val => typeof val === 'number' && val >= m);
                    if (newStorage[key].length === 0) delete newStorage[key];
                }
            }
            jsonString = JSON.stringify(myStorage);
            trialN--;
        }
        if (jsonString.length <= 4194304) {
            // localStorageに入れる
            localStorage._supportRead = jsonString;
        }
    }

    function changeColor(entry, readColor) {
        const f = () => {
            entry.style.background = readColor;
        }
        if (typeof Promise !== 'undefined') {
            Promise.resolve().then(f);
        } else {
            f();
        }
    }

    for (let i = 0, len = entries.length; i < len; i++) {
        const entry = entries[i];
        const f = {
            thumb: entry.querySelector(".entry > .entry-thumb > a > img[src]"),
            date: entry.querySelector(".entry > .entry-date"),
            title: entry.querySelector(".entry > .entry-title > [href]"),
            anchor: entry.querySelector(".entry-text > [href]")
        }
        if (!f.thumb || !f.date) continue;
        const mangaId = f.thumb.src.split("/").slice(-1)[0].replace(".jpg", "");
        if (!mangaId) continue;
        // 24時間以内の更新だと表記が変わる
        const dateText = f.date.textContent;
        let date = /^\d+時間前|^\d+分前|^\d+秒前/.test(dateText)
            ? calcAgoDate(nowDate, dateText.match(/^\d+/)[0], dateText.match(/時間前|分前|秒前/)[0]) : dateText.replace(/\b(\d)\b/g, '0$1').replace(/\//g, "");
        date = +date;
        if (!(date > 19691231)) continue;
        if (mangaId in myStorage && myStorage[mangaId].includes(date)) changeColor(entry, readColor);

        if (f.title) {
            f.title.addEventListener("click", { i, mangaId, date, handleEvent });
            f.title.addEventListener("auxclick", { i, mangaId, date, handleEvent });
        }
        if (f.anchor) {
            f.anchor.addEventListener("click", { i, mangaId, date, handleEvent });
            f.anchor.addEventListener("auxclick", { i, mangaId, date, handleEvent });
        }
    }
})();

また書き直しました。

// ==UserScript==
// @name         Web漫画アンテナ 既読対応
// @namespace
// @description マイリストのページで既読漫画の背景色を変えます
// @version      0.21
// @author       kiyo
// @match        https://webcomics.jp/mylist
// @match        https://webcomics.jp/mylist*
// @grant        none
// @namespace 
// ==/UserScript==

(function () {
    let myStorage = null;
    try {
        myStorage = JSON.parse(localStorage._supportRead);
    } catch {
        myStorage = {};
    }
    if (!myStorage._VERSION_) {
        const newStorage = {};
        for (const [key, value] of Object.entries(myStorage)) {
            if (value && value.length >= 1 && value.unshift) newStorage[key] = value.filter(val => typeof val === 'string' && val.length === 8).map(val => +val).filter(val > 19691231)
        }
        myStorage = newStorage;
        myStorage._VERSION_ = 1;
        localStorage._supportRead = JSON.stringify(myStorage);
    }
    if (myStorage._VERSION_ !== 1) {
        console.error("エラーが発生しました - データベースのバージョンが正しくありません。");
        return;
    }
    const readColor = "#c5c5c6";
    const nowDate = new Date();

    const timeToMsec = (num, unit) => {
        // サイト内の時間表示が切り上げなので-1しておく(24時に更新した作品が時間により日付が前後してしまうのを回避)
        num = num - 1;
        switch (unit) {
            case "時間前":
                return num * 60 * 60 * 1000;
            case "分前":
                return num * 60 * 1000;
            case "秒前":
                return num * 1000;
            default:
                console.error(`timeToMsec Error: ${num}${unit}`);
        }
    }
    const dateToStr = (year, month, day) => `${year}${("0" + month).slice(-2)}${("0" + day).slice(-2)}`;
    const calcAgoDate = (nowDate, num, unit) => {
        let ago = timeToMsec(parseInt(num), unit);
        //console.log(ago, num, unit);
        const agoDate = new Date(nowDate - ago);
        const year = agoDate.getFullYear();
        const month = agoDate.getMonth() + 1;
        const day = agoDate.getDate();
        const result = dateToStr(year, month, day);
        if (typeof result !== 'string' || result.length !== 8) console.error("エラーが発生しました - 時間文字列の構文が正しくありません。")
        return result;
    }

    const entries = document.querySelectorAll(".entry");

    //function test(){console.log(this.i +","+ this.mangaId +","+ this.date);};
    function handleEvent() {
        let { i, mangaId, date } = this;
        date = +date;
        if (!(date > 19691231)) return;

        changeColor(entries[i], readColor);
        // 重複チェック&追加
        if (!(mangaId in myStorage)) {
            myStorage[mangaId] = [date];
        } else if (!(myStorage[mangaId].includes(date))) {
            myStorage[mangaId].push(date);
        }
        let jsonString = JSON.stringify(myStorage);

        let trialN = 4;
        // 4MB(4194304文字)以上になったら先頭から削除
        while (jsonString.length > 4194304 && trialN >= 1) {
            let arr = new Set();
            jsonString.replace(/\b\d{8}\b/g, (val) => {
                if (+val > 19691231 && +val < 29990101) {
                    arr.add(+val);
                }
            });
            arr = [...arr.values()].sort();
            let m = arr[Math.round(arr.length / 2)];
            const newStorage = Object.assign({}, myStorage);
            for (const [key, value] of Object.entries(myStorage)) {
                if (value && value.length >= 1 && value.unshift) {
                    newStorage[key] = value.filter(val => typeof val === 'number' && val >= m);
                    if (newStorage[key].length === 0) delete newStorage[key];
                }
            }
            myStorage = newStorage;
            jsonString = JSON.stringify(myStorage);
            trialN--;
        }
        if (jsonString.length <= 4194304) {
            // localStorageに入れる
            localStorage._supportRead = jsonString;
        }
    }

    function changeColor(entry, readColor) {
        const f = () => {
            entry.style.background = readColor;
        }
        if (typeof Promise !== 'undefined') {
            Promise.resolve().then(f);
        } else {
            f();
        }
    }

    for (let i = 0, len = entries.length; i < len; i++) {
        const entry = entries[i];
        const f = {
            thumb: entry.querySelector(".entry > .entry-thumb > a > img[src]"),
            date: entry.querySelector(".entry > .entry-date"),
            title: entry.querySelector(".entry > .entry-title > [href]"),
            anchor: entry.querySelector(".entry-text > [href]")
        }
        if (!f.thumb || !f.date) continue;
        const mangaId = f.thumb.src.split("/").slice(-1)[0].replace(".jpg", "");
        if (!mangaId) continue;
        // 24時間以内の更新だと表記が変わる
        const dateText = f.date.textContent;
        let date = /^\d+時間前|^\d+分前|^\d+秒前/.test(dateText)
            ? calcAgoDate(nowDate, dateText.match(/^\d+/)[0], dateText.match(/時間前|分前|秒前/)[0]) : dateText.replace(/\b(\d)\b/g, '0$1').replace(/\//g, "");
        date = +date;
        if (!(date > 19691231)) continue;
        if (mangaId in myStorage && myStorage[mangaId].includes(date)) changeColor(entry, readColor);

        if (f.title) {
            f.title.addEventListener("click", { i, mangaId, date, handleEvent });
            f.title.addEventListener("auxclick", { i, mangaId, date, handleEvent });
        }
        if (f.anchor) {
            f.anchor.addEventListener("click", { i, mangaId, date, handleEvent });
            f.anchor.addEventListener("auxclick", { i, mangaId, date, handleEvent });
        }
    }
})();
§
작성: 2023-08-15

おっと、レスつけてもらってたのに読まずにソース直してたわ
時間表記にタブや改行がつくようになった?のが原因だったので
69行目を
const dateText = e.date[i].textContent.replace(/\n|\t/g, '');
で以前のように動作するようになりました

貼ってもらってるコードはコンソールでエラー出てて機能しなかったけど、オレ環なのでしょう

おっと、レスつけてもらってたのに読まずにソース直してたわ
時間表記にタブや改行がつくようになった?のが原因だったので
69 行目を
const dateText = e.date[i].textContent.replace(/\n|\t/g, '');
で以前のように動作するようになりました

貼ってもらってるコードはコンソールでエラー出てて機能しなかったけど、オレ環なのでしょう

なるほど、実際に使ったことがないから。

const dateText = e.date[i].textContent.replace(/\d+\s*:\s*\d+\s*:\s*\d+/g, '').trim();

このよりに直すかもしれませんね〜

댓글 남기기

댓글을 남기려면 로그인하세요.