Batoto Quick Links

Add convenient links to Batoto series pages.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         Batoto Quick Links
// @namespace    Doomcat55
// @version      0.3
// @description  Add convenient links to Batoto series pages.
// @author       Doomcat55
// @match        *://bato.to/reader
// @match        *://bato.to/comic/_/comics/*
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_listValues
// @grant        GM_download
// @grant        GM_registerMenuCommand
// ==/UserScript==

(function matchURL(path) {
    switch (true) {
        case /\/reader/.test(path):
            setBookmarks();
            break;
        case /\/comic\/_\/comics/.test(path):
            showBookmarks();
            break;
    }
})(window.location.pathname);


function parseSeriesID(link) {
    const text = link.match(/-r(\d+)/)[1];
    return parseInt(text);
}

function setBookmarks() {
    const reader = document.getElementById('reader');

    const observer = new MutationObserver(() => {
        const seriesID = parseSeriesID(document.querySelector('a[href*="/comic/"]').pathname);
        const pageID = window.location.hash;
        GM_setValue(seriesID, pageID);
    });

    observer.observe(reader, {childList: true});
}

function showBookmarks() {
    const seriesID = parseSeriesID(window.location.pathname);
    const bookmarkedPage = GM_getValue(seriesID);
    const linkedPage = bookmarkedPage || (document.querySelector('.chapter_row:nth-last-child(2) td:first-child a') || {}).hash;
    if (linkedPage) {
        const quickLink = document.createElement('a');
        quickLink.href = `/reader${linkedPage}`;
        quickLink.className = 'ipsButton_secondary';
        quickLink.innerHTML = bookmarkedPage ? 'Resume reading' : 'First chapter';
        const linkParent = document.querySelector('.__like.right');
        linkParent.insertBefore(quickLink, linkParent.firstChild);
    }
}


function exportBookmarks() {
    const data = GM_listValues().map(key => [key, GM_getValue(key)]);
    const url = `data:application/json,${encodeURIComponent(JSON.stringify(data))}`;
    GM_download({
        url: url,
        name: 'batoto-bookmarks.json',
        onerror: download => {
            console.log(download);
        }
    });
}


function acceptUpload({ accept }, handleFile) {
    const button = document.createElement('button');
    const input = document.createElement('input');

    button.innerHTML = 'Click to import';
    button.setAttribute('style', 'position: fixed; width: 100px; height: 50px; left: calc(50vw - 50px); top: calc(50vh - 25px);');
    button.addEventListener('click', () => {
        input.click();
        document.body.removeChild(button);
    });

    input.setAttribute('type', 'file');
    if (accept) {
        input.setAttribute('accept', accept);
    }
    input.setAttribute('style', 'display: none;');
    input.addEventListener('change', event => {
        handleFile(input.files[0]);
    });

    document.body.append(button);
}


function importBookmarks() {
    acceptUpload({ accept: 'application/json' }, file => {
        const fileReader = new FileReader();
        fileReader.addEventListener('load', event => {
            let json, map;
            if (json = event.target.result, map = new Map(JSON.parse(json))) {
                map.forEach((value, key) => {
                    GM_setValue(key, value);
                });
                alert('Successfully imported bookmarks.');
            }
        });
        fileReader.readAsText(file);
    });
}


GM_registerMenuCommand('Import bookmarks', importBookmarks);
GM_registerMenuCommand('Export bookmarks', exportBookmarks);