Add convenient links to Batoto series pages.
// ==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);