Last active
November 11, 2022 01:25
-
-
Save sorz/714b547ce2101866075aeeffe77675f8 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ==UserScript== | |
// @name E-Hentai Prefetch Next Page | |
// @namespace Violentmonkey Scripts | |
// @match https://e-hentai.org/s/* | |
// @match https://exhentai.org/s/* | |
// @grant none | |
// @version 0.2.0 | |
// @author sorz | |
// @description Prefetch image file on the next page for faster browsing. | |
// ==/UserScript== | |
const MAX_PREFETCH_PAGES = 4; | |
// page no -> response from api_response | |
const pageRespCache = new Map(); | |
// page no. -> image key | |
const pageImgKeyCache = new Map(); | |
const currentPageNo = () => history.state.page; | |
const getPageNoImgKey = (doc) => { | |
let [_, page, imgKey] = doc.querySelector('a#next') | |
.attributes.onclick.value | |
.match(/load_image\((\d+), '([0-9a-f]+)'\)/); | |
return [parseInt(page), imgKey]; | |
}; | |
const template = (html) => { | |
const template = document.createElement('template'); | |
template.innerHTML = html; | |
return template.content; | |
} | |
function prefetchPage(pageNo, n) { | |
const onResponse = (resp) => { | |
const [nextPageNo, nextImgKey] = getPageNoImgKey(template(resp.n)); | |
if (!pageRespCache.has(pageNo)) { | |
// Cache response | |
pageRespCache.set(pageNo, resp); | |
pageImgKeyCache.set(nextPageNo, nextImgKey); | |
// Prefetch image file | |
const src = template(resp.i3).querySelector('img#img').src; | |
const img = new Image(); | |
img.onload = () => console.log('image fetched', 'page', pageNo); | |
img.src = src; | |
} | |
if (n > 0) prefetchPage(nextPageNo, n - 1); | |
} | |
if (pageRespCache.has(pageNo)) { | |
onResponse(pageRespCache.get(pageNo)); | |
return; | |
} | |
const imgKey = pageImgKeyCache.get(pageNo); | |
if (!imgKey) { | |
logging.warn('missing image key for page', pageNo); | |
return; | |
} | |
const request = { | |
method: "showpage", | |
gid: gid, | |
page: pageNo, | |
imgkey: imgKey, | |
showkey: showkey | |
}; | |
const xhr = new XMLHttpRequest(); | |
api_call(xhr, request, () => { | |
const resp = api_response(xhr); | |
if (resp == false || resp.error != undefined) return; | |
onResponse(resp); | |
}); | |
} | |
function prefetchNextNPage(n) { | |
let [pageNo, imgKey] = getPageNoImgKey(document); | |
pageImgKeyCache.set(pageNo, imgKey); | |
prefetchPage(pageNo, n); | |
} | |
apply_json_state = new Proxy(apply_json_state, { | |
apply: function(target, thisArg, args) { | |
Reflect.apply(target, thisArg, args); | |
prefetchNextNPage(MAX_PREFETCH_PAGES); | |
} | |
}); | |
load_image = new Proxy(load_image, { | |
apply: function(target, thisArg, [page, imgKey]) { | |
const resp = pageRespCache.get(page); | |
if (!resp) return Reflect.apply(target, thisArg, [page, imgKey]); | |
console.log('cached resp found', 'page', page); | |
history.pushState( | |
{ | |
page: resp.p, | |
imgkey: resp.k, | |
json: resp, | |
expire: get_unixtime() + 300 | |
}, | |
document.title, | |
base_url + resp.s | |
); | |
apply_json_state(resp); | |
return false; | |
} | |
}); | |
prefetchNextNPage(MAX_PREFETCH_PAGES); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment