// ==UserScript==
// @name la-image-extractor
// @name:zh-CN la 图片地址复制
// @description copy image source in hitomi.la notomi.la e-hentai.org to clipboard
// @description:zh-CN 复制 hitoma.la notomi.la e-hentai 图片链接到剪贴板
// @version 0.2.5
// @author jferroal
// @license GPL-3.0
// @require https://greasyfork.org/scripts/31793-jmul/code/JMUL.js?version=209567
// @include https://hitomi.la/reader/*
// @include https://nozomi.la/tag/*
// @include https://e-hentai.org/s/*
// @grant GM_xmlhttpRequest
// @run-at document-idle
// @namespace https://greasyfork.org/users/34556-jferroal
// ==/UserScript==
(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
class Button {
constructor(label, eventHandlers = []) {
this.element = document.createElement('div');
this.addCss(Button.DefaultCss);
this.element.innerText = label;
this.listeners = {};
this.listen(eventHandlers);
this.parent = null;
}
onClick(handler) {
this.listen({'click': handler});
}
listen(handlers) {
for (const event in handlers) {
if (handlers.hasOwnProperty(event)) {
this.element.addEventListener(event, handlers[event]);
}
}
}
addCss(css) {
for (const styleName in css) {
if (css.hasOwnProperty(styleName)) {
this.element.style[styleName] = css[styleName];
}
}
}
appendTo(element) {
this.parent = element;
element.appendChild(this.element);
}
removeFrom() {
this.parent.removeChild(this.element);
}
removeListener() {
for (const event in this.listeners) {
if (this.listeners.hasOwnProperty(event)) {
this.element.removeEventListener(event, this.listeners[event]);
}
}
}
}
Button.DefaultCss = {
textAlign: 'center',
width: '120px',
lineHeight: '40px',
backgroundColor: 'skyblue',
color: 'white',
cursor: 'pointer',
borderRadius: '8px',
boxShadow: '0px 0px 8px 4px rgba(0, 0, 0, .2)',
position: 'fixed',
right: '80px',
bottom: '80px'
};
module.exports = Button;
},{}],2:[function(require,module,exports){
const {createFullScreenElement, href, innerText, isEhentai} = require('./utils');
let _EhentaiState = {};
function constructImage(src) {
const img = document.createElement('img');
img.style.width = '100vw';
img.style.maxWidth = '100vw';
img.setAttribute('src', src);
return img;
}
function loadMore() {
_EnthtaiState.ImageContainer.removeChild(_EhentaiState.LoadMoreBtn);
const targets = _EhentaiState.ImageSources
.slice(_EhentaiState.ImageAppendedCount, _EhentaiState.ImageAppendedCount + IMAGE_PER_PAGE);
let i = 0;
for (const src of targets) {
let timer = setTimeout(() => {
const img = constructImage(src);
document.querySelector(_EhentaiState.ImageContainerSelector).appendChild(img);
clearTimeout(timer);
timer = null;
}, i * _EhentaiState.ImageElementCreationDefer);
_EhentaiState.ImageAppendedCount += 1;
i += 1;
}
if (_EhentaiState.ImageAppendedCount < _EhentaiState.ImageSources.length) {
_EhentaiState.ImageContainer.appendChild(_EhentaiState.LoadMoreBtn);
}
}
module.exports = {
initEhentai() {
if (!isEhentai()) return;
const [
MainContainerSelector,
TopPaginationSelector,
ImageContainerSelector,
BottomPaginationSelector,
ImagesSelector,
TitleSelector
] = ['#i1', '#i2', '#i3', '#i4', '#i3 img', 'title'];
const NextPagePattern = /<div id="i3"><a onclick="return load_image\((\d+), '([\w\d]+)'\)"/gi;
const ImageSourcePattern = /<img id="img" src="(.*)" style=".*?" onerror=".*?" \/>/gi;
const ImageElementCreationDefer = 200;
const ImagePerPage = 20;
const PostId = href().split('/')[5].split('-')[0];
const ImageContainer = document.querySelector(ImageContainerSelector);
const LoadMoreBtn = document.createElement('div');
LoadMoreBtn.style.width = '100%';
LoadMoreBtn.style.lineHeight = '48px';
LoadMoreBtn.style.margin = '24px 60px';
LoadMoreBtn.style.cursor = 'pointer';
LoadMoreBtn.style.backgroundColor = 'lightskyblue';
LoadMoreBtn.style.borderRadius = '8px';
LoadMoreBtn.innerText = 'LOAD MORE';
LoadMoreBtn.addEventListener('click', loadMore);
let FetchAllRunning = false;
let ImageAppendedCount = 1;
let ImageSources = ['first_image_placeholder'];
_EhentaiState = {
MainContainerSelector,
TopPaginationSelector,
ImageContainerSelector,
BottomPaginationSelector,
ImagesSelector,
TitleSelector,
NextPagePattern,
ImageSourcePattern,
ImageElementCreationDefer,
ImagePerPage,
PostId,
ImageContainer,
LoadMoreBtn,
ImageAppendedCount,
ImageSources,
FetchAllRunning,
}
},
fetchEhentaiAll() {
if (_EhentaiState.FetchAllRunning) return;
_EhentaiState.FetchAllRunning = true;
function getNextImage(page, hash) {
const url = `https://e-hentai.org/s/${hash}/${_EhentaiState.PostId}-${page}`;
const xmlhttp = new XMLHttpRequest();
xmlhttp.open('GET', url);
xmlhttp.onreadystatechange = function () {
if (this.readyState !== 4) return;
if (this.status === 200) {
const [, p, h] = _EnthtaiState.NextPagePattern.exec(this.responseText);
_EhentaiState.NextPagePattern.lastIndex = -1;
const hasNext = parseInt(p, 10) !== _EhentaiState.ImageSources.length;
if (!hasNext) {
const loadedElem = createFullScreenElement('ALL IMAGE SOURCES LOADED');
document.body.appendChild(loadedElem);
let timer = setTimeout(() => {
document.body.removeChild(loadedElem);
clearTimeout(timer);
timer = null;
}, 3000);
_EhentaiState.FetchAllRunning = false;
return;
}
const [, imageSource] = _EhentaiState.ImageSourcePattern.exec(this.responseText);
_EhentaiState.ImageSourcePattern.lastIndex = -1;
_EhentaiState.ImageSources.push(imageSource);
if (_EhentaiState.ImageAppendedCount < _EhentaiState.ImagePerPage) {
// load IMAGE PER PAGE COUNT image at first
const img = constructImage(imageSource);
_EhentaiState.ImageContainer.appendChild(img);
image_appended_count += 1;
} else {
ImageContainer.appendChild(_EhentaiState.LoadMoreBtn);
}
getNextImage(p, h);
}
};
xmlhttp.send();
}
const mainContainer = document.querySelector(_EhentaiState.MainContainerSelector);
window.addEventListener('resize', () => {
document.querySelector(_EhentaiState.MainContainerSelector).style.maxWidth = '100vw';
});
mainContainer.style.width = '100vw';
mainContainer.style.maxWidth = '100vw';
document.querySelector(_EhentaiState.TopPaginationSelector).style.display = 'none';
document.querySelector(_EhentaiState.BottomPaginationSelector).style.display = 'none';
const [, page, hash] = _EhentaiState.NextPagePattern.exec(
document.querySelector(_EhentaiState.MainContainerSelector).innerHTML
);
getNextImage(page, hash);
},
extractEhentaiImages() {
const img = document.querySelector(_EhentaiState.ImagesSelector);
const title = innerText(document.querySelector(_EhentaiState.TitleSelector));
return `${title}\n${[img.src, ..._EhentaiState.ImageSources.slice(1)].join('\n')}\n${'= ='.repeat(20)}`;
}
};
},{"./utils":6}],3:[function(require,module,exports){
const {href, innerText, isHitomi} = require('./utils');
let _HitomiState = {};
module.exports = {
initHitomi() {
if (!isHitomi()) return;
_HitomiState.ImagesSrcSelector = '.image-url';
_HitomiState.TitleSelector = 'title';
_HitomiState.Adapost = false;
_HitomiState.NumberOfFrontEnds = 2;
},
extractHitomiImages() {
const {ImagesSrcSelector, TitleSelector, Adapost, NumberOfFrontEnds} = _HitomiState;
let images = Array.from(document.querySelectorAll(ImgSrcSelector));
let title = encodeURIComponent(innerText(document.querySelector(TitleSelector), '- | -').split(' | ')[0]);
const mat = /\/\d*(\d)\.html/.exec(href());
let lv = mat && parseInt(mat[1], 10);
if (!lv || Number.isNaN(lv)) {
lv = '1';
}
const magic = Adapost ? 'a' : String.fromCharCode(((lv === 1 ? 0 : lv) % NumberOfFrontends) + 97);
images = images.map(s => s.innerText.replace('//g.hitomi.la', `https://${magic}a.hitomi.la`));
return `${title}\n${images.join('\n')}\n${'= ='.repeat(20)}`;
}
};
},{"./utils":6}],4:[function(require,module,exports){
const {isHitomi, isNozomi, isEhentai, copyToClipboard} = require('./utils');
const Button = require('./Button');
const {initHitomi, extractHitomiImages} = require('./hitomi');
const {initNozomi, extractNozomiImages, fetchNozomiAll} = require('./nozomi');
const {initEhentai, extractEhentaiImages, fetchEhentaiAll} = require('./ehentai');
(function () {
initHitomi();
initNozomi();
initEhentai();
// create button to click
if (isNozomi() || isEhentai()) {
const btn = new Button('Fetch All');
btn.addCss({bottom: '160px', zIndex: '999'});
btn.appendTo(document.body);
btn.onClick(() => {
if (isNozomi()) {
fetchNozomiAll();
}
if (isEhentai()) {
fetchEhentaiAll();
}
});
}
const btn = new Button('Copy Sources');
btn.addCss({zIndex: '999'});
btn.onClick(() => {
// prepare str2Paste
let str2paste = '';
if (isHitomi()) {
str2paste = extractHitomiImages();
} else if (isNozomi()) {
str2paste = extractNozomiImages();
} else {
str2paste = extractEhentaiImages();
}
copyToClipboard(str2paste);
});
btn.appendTo(document.body);
})();
},{"./Button":1,"./ehentai":2,"./hitomi":3,"./nozomi":5,"./utils":6}],5:[function(require,module,exports){
const {innerText, createFullScreenElement} = require('./utils');
// TODO: refactor
const [
ImgSrcSelector,
TitleSelector,
ContentSelector,
ThumbnailDivsSelector
] = ['.tag-list-img', 'h1', '.content', '#thumbnail-divs'];
function JSPack() {
// Module-level (private) variables
var el, bBE = false, m = this;
// Raw byte arrays
m._DeArray = function (a, p, l) {
return [a.slice(p, p + l)];
};
m._EnArray = function (a, p, l, v) {
for (var i = 0; i < l; a[p + i] = v[i] ? v[i] : 0, i++) ;
};
// ASCII characters
m._DeChar = function (a, p) {
return String.fromCharCode(a[p]);
};
m._EnChar = function (a, p, v) {
a[p] = v.charCodeAt(0);
};
// Little-endian (un)signed N-byte integers
m._DeInt = function (a, p) {
var lsb = bBE ? (el.len - 1) : 0, nsb = bBE ? -1 : 1, stop = lsb + nsb * el.len, rv, i, f;
for (rv = 0, i = lsb, f = 1; i != stop; rv += (a[p + i] * f), i += nsb, f *= 256) ;
if (el.bSigned && (rv & Math.pow(2, el.len * 8 - 1))) { rv -= Math.pow(2, el.len * 8); }
return rv;
};
m._EnInt = function (a, p, v) {
var lsb = bBE ? (el.len - 1) : 0, nsb = bBE ? -1 : 1, stop = lsb + nsb * el.len, i;
v = (v < el.min) ? el.min : (v > el.max) ? el.max : v;
for (i = lsb; i != stop; a[p + i] = v & 0xff, i += nsb, v >>= 8) ;
};
// ASCII character strings
m._DeString = function (a, p, l) {
for (var rv = new Array(l), i = 0; i < l; rv[i] = String.fromCharCode(a[p + i]), i++) ;
return rv.join('');
};
m._EnString = function (a, p, l, v) {
for (var t, i = 0; i < l; a[p + i] = (t = v.charCodeAt(i)) ? t : 0, i++) ;
};
// Little-endian N-bit IEEE 754 floating point
m._De754 = function (a, p) {
var s, e, m, i, d, nBits, mLen, eLen, eBias, eMax;
mLen = el.mLen, eLen = el.len * 8 - el.mLen - 1, eMax = (1 << eLen) - 1, eBias = eMax >> 1;
i = bBE ? 0 : (el.len - 1);
d = bBE ? 1 : -1;
s = a[p + i];
i += d;
nBits = -7;
for (e = s & ((1 << (-nBits)) - 1), s >>= (-nBits), nBits += eLen; nBits > 0; e = e * 256 + a[p + i], i += d, nBits -= 8) ;
for (m = e & ((1 << (-nBits)) - 1), e >>= (-nBits), nBits += mLen; nBits > 0; m = m * 256 + a[p + i], i += d, nBits -= 8) ;
switch (e) {
case 0:
// Zero, or denormalized number
e = 1 - eBias;
break;
case eMax:
// NaN, or +/-Infinity
return m ? NaN : ((s ? -1 : 1) * Infinity);
default:
// Normalized number
m = m + Math.pow(2, mLen);
e = e - eBias;
break;
}
return (s ? -1 : 1) * m * Math.pow(2, e - mLen);
};
m._En754 = function (a, p, v) {
var s, e, m, i, d, c, mLen, eLen, eBias, eMax;
mLen = el.mLen, eLen = el.len * 8 - el.mLen - 1, eMax = (1 << eLen) - 1, eBias = eMax >> 1;
s = v < 0 ? 1 : 0;
v = Math.abs(v);
if (isNaN(v) || (v === Infinity)) {
m = isNaN(v) ? 1 : 0;
e = eMax;
}
else {
e = Math.floor(Math.log(v) / Math.LN2); // Calculate log2 of the value
if (v * (c = Math.pow(2, -e)) < 1) {
e--;
c *= 2;
} // Math.log() isn't 100% reliable
// Round by adding 1/2 the significand's LSD
if (e + eBias >= 1) { v += el.rt / c; } // Normalized: mLen significand digits
else { v += el.rt * Math.pow(2, 1 - eBias); } // Denormalized: <= mLen significand digits
if (v * c >= 2) {
e++;
c /= 2;
} // Rounding can increment the exponent
if (e + eBias >= eMax) {
// Overflow
m = 0;
e = eMax;
}
else if (e + eBias >= 1) {
// Normalized - term order matters, as Math.pow(2, 52-e) and v*Math.pow(2, 52) can overflow
m = (v * c - 1) * Math.pow(2, mLen);
e = e + eBias;
}
else {
// Denormalized - also catches the '0' case, somewhat by chance
m = v * Math.pow(2, eBias - 1) * Math.pow(2, mLen);
e = 0;
}
}
for (i = bBE ? (el.len - 1) : 0, d = bBE ? -1 : 1; mLen >= 8; a[p + i] = m & 0xff, i += d, m /= 256, mLen -= 8) ;
for (e = (e << mLen) | m, eLen += mLen; eLen > 0; a[p + i] = e & 0xff, i += d, e /= 256, eLen -= 8) ;
a[p + i - d] |= s * 128;
};
// Class data
m._sPattern = '(\\d+)?([AxcbBhHsfdiIlL])';
m._lenLut = {
'A': 1,
'x': 1,
'c': 1,
'b': 1,
'B': 1,
'h': 2,
'H': 2,
's': 1,
'f': 4,
'd': 8,
'i': 4,
'I': 4,
'l': 4,
'L': 4
};
m._elLut = {
'A': {en: m._EnArray, de: m._DeArray},
's': {en: m._EnString, de: m._DeString},
'c': {en: m._EnChar, de: m._DeChar},
'b': {en: m._EnInt, de: m._DeInt, len: 1, bSigned: true, min: -Math.pow(2, 7), max: Math.pow(2, 7) - 1},
'B': {en: m._EnInt, de: m._DeInt, len: 1, bSigned: false, min: 0, max: Math.pow(2, 8) - 1},
'h': {en: m._EnInt, de: m._DeInt, len: 2, bSigned: true, min: -Math.pow(2, 15), max: Math.pow(2, 15) - 1},
'H': {en: m._EnInt, de: m._DeInt, len: 2, bSigned: false, min: 0, max: Math.pow(2, 16) - 1},
'i': {en: m._EnInt, de: m._DeInt, len: 4, bSigned: true, min: -Math.pow(2, 31), max: Math.pow(2, 31) - 1},
'I': {en: m._EnInt, de: m._DeInt, len: 4, bSigned: false, min: 0, max: Math.pow(2, 32) - 1},
'l': {en: m._EnInt, de: m._DeInt, len: 4, bSigned: true, min: -Math.pow(2, 31), max: Math.pow(2, 31) - 1},
'L': {en: m._EnInt, de: m._DeInt, len: 4, bSigned: false, min: 0, max: Math.pow(2, 32) - 1},
'f': {en: m._En754, de: m._De754, len: 4, mLen: 23, rt: Math.pow(2, -24) - Math.pow(2, -77)},
'd': {en: m._En754, de: m._De754, len: 8, mLen: 52, rt: 0}
};
// Unpack a series of n elements of size s from array a at offset p with fxn
m._UnpackSeries = function (n, s, a, p) {
for (var fxn = el.de, rv = [], i = 0; i < n; rv.push(fxn(a, p + i * s)), i++) ;
return rv;
};
// Pack a series of n elements of size s from array v at offset i to array a at offset p with fxn
m._PackSeries = function (n, s, a, p, v, i) {
for (var fxn = el.en, o = 0; o < n; fxn(a, p + o * s, v[i + o]), o++) ;
};
// Unpack the octet array a, beginning at offset p, according to the fmt string
m.Unpack = function (fmt, a, p) {
// Set the private bBE flag based on the format string - assume big-endianness
bBE = (fmt.charAt(0) != '<');
p = p ? p : 0;
var re = new RegExp(this._sPattern, 'g'), m, n, s, rv = [];
while (m = re.exec(fmt)) {
n = ((m[1] == undefined) || (m[1] == '')) ? 1 : parseInt(m[1]);
s = this._lenLut[m[2]];
if ((p + n * s) > a.length) {
return undefined;
}
switch (m[2]) {
case 'A':
case 's':
rv.push(this._elLut[m[2]].de(a, p, n));
break;
case 'c':
case 'b':
case 'B':
case 'h':
case 'H':
case 'i':
case 'I':
case 'l':
case 'L':
case 'f':
case 'd':
el = this._elLut[m[2]];
rv.push(this._UnpackSeries(n, s, a, p));
break;
}
p += n * s;
}
return Array.prototype.concat.apply([], rv);
};
// Pack the supplied values into the octet array a, beginning at offset p, according to the fmt string
m.PackTo = function (fmt, a, p, values) {
// Set the private bBE flag based on the format string - assume big-endianness
bBE = (fmt.charAt(0) !== '<');
var re = new RegExp(this._sPattern, 'g'), m, n, s, i = 0, j;
while (m = re.exec(fmt)) {
n = ((m[1] === undefined) || (m[1] === '')) ? 1 : parseInt(m[1]);
s = this._lenLut[m[2]];
if ((p + n * s) > a.length) {
return false;
}
switch (m[2]) {
case 'A':
case 's':
if ((i + 1) > values.length) { return false; }
this._elLut[m[2]].en(a, p, n, values[i]);
i += 1;
break;
case 'c':
case 'b':
case 'B':
case 'h':
case 'H':
case 'i':
case 'I':
case 'l':
case 'L':
case 'f':
case 'd':
el = this._elLut[m[2]];
if ((i + n) > values.length) { return false; }
this._PackSeries(n, s, a, p, values, i);
i += n;
break;
case 'x':
for (j = 0; j < n; j++) { a[p + j] = 0; }
break;
}
p += n * s;
}
return a;
};
// Pack the supplied values into a new octet array, according to the fmt string
m.Pack = function (fmt, values) {
return this.PackTo(fmt, new Array(this.CalcLength(fmt)), 0, values);
};
// Determine the number of bytes represented by the format string
m.CalcLength = function (fmt) {
var re = new RegExp(this._sPattern, 'g'), m, sum = 0;
while (m = re.exec(fmt)) {
sum += (((m[1] == undefined) || (m[1] == '')) ? 1 : parseInt(m[1])) * this._lenLut[m[2]];
}
return sum;
};
}
var nozomiextension = '.nozomi';
var nozomidir = 'nozomi';
var domain = 'n.nozomi.la';
var postdir = 'post';
var results_array = {};
var outstanding_requests = {};
var number_of_outstanding_requests = 0;
var nozomi, total_items;
var tag, tag_for_hash = '', area, page_number;
var nozomi_address;
function dgebi(id) { return document.getElementById(id); }
function path_from_postid(postid) {
if (postid.length < 3) return postid;
return postid.replace(/^(.*(..)(.))$/, '$3/$2/$1');
}
function resize_thumbnails() {
var c = document.getElementsByClassName('content')[0];
if (!c) {
return;
}
var s = c.clientWidth;
var n = Math.ceil(6.0 * s / 1000.0);
var w = ((s - (10.0 * n + 10.0) - 0.5) / n) - 2.0;
var divs = document.getElementsByClassName('thumbnail-div');
for (var i = 0; i < divs.length; i++) {
var div = divs[i];
div.style.width = (w + 'px');
div.style.height = (w + 'px');
}
}
function check_dates() {
var format = 'lll';
var localize_title = function (el) {
if (!el) {
return;
}
var str = el.title;
if (str) {
var m = moment(str);
el.title = m.format(format);
}
};
//post view
localize_title(document.querySelectorAll('.post img')[0]);
}
function urlencode(str) {
return str.replace(/[;\/?:@=&]/g, function (c) {
return '%' + c.charCodeAt(0).toString(16);
return '%' + c.charCodeAt(0).toString(16);
});
}
function fetch_nozomi(totalImageCount) {
var filepath = decodeURIComponent(document.location.href.replace(/.*nozomi\.la\//, ''));
if (!filepath) {
tag = 'index';
page_number = 1;
} else {
var elements = filepath.replace(/\.html$/, '').split('-');
if (elements.length < 2) return;
while (elements.length > 2) {
elements[1] = elements[0] + '-' + elements[1];
elements.shift();
}
tag = elements[0];
if (tag.match(/\//)) {
var area_elements = tag.split(/\//);
if (area_elements.length !== 2) return;
area = area_elements[0];
if (!area || area.match(/[^A-Za-z0-9_]/)) return;
tag = area_elements[1];
}
if (!tag || tag.match(/\//)) return;
if (tag === 'index-Popular') {
tag_for_hash = '-Popular';
} else if (area) {
tag_for_hash = tag;
}
page_number = parseInt(elements[1]);
if (!page_number || page_number < 1) return;
}
nozomi_address = '//' + [domain, urlencode(tag)].join('/') + nozomiextension;
if (area) {
nozomi_address = '//' + [domain, nozomidir, urlencode(tag)].join('/') + nozomiextension;
}
var start_byte = 0;
var end_byte = totalImageCount * 4 - 1;
var xhr = new XMLHttpRequest();
const loadingElement = createFullScreenElement();
document.body.appendChild(loadingElement);
xhr.open('GET', nozomi_address);
xhr.responseType = 'arraybuffer';
xhr.setRequestHeader('Range', 'bytes=' + start_byte.toString() + '-' + end_byte.toString());
xhr.onreadystatechange = function (oEvent) {
if (xhr.readyState === 4) {
if (xhr.status === 200 || xhr.status === 206) {
var arrayBuffer = xhr.response; // Note: not oReq.responseText
if (arrayBuffer) {
var arr = new Uint8Array(arrayBuffer); //e.g. [0x00, 0x5D, 0x39, 0x72, 0x00, 0x5D, 0x39, 0x82, ...]
var jspack = new JSPack();
var total = arr.length / 4; //32-bit unsigned integers
nozomi = jspack.Unpack(total + 'I', arr);
total_items = parseInt(xhr.getResponseHeader('Content-Range').replace(/^[Bb]ytes \d+-\d+\//, '')) / 4;
get_jsons();
document.body.removeChild(loadingElement);
}
}
}
};
xhr.send();
}
function get_jsons() {
var datas = [];
for (var i in nozomi) {
var postid = nozomi[i];
if (postid in results_array) {
datas.push(results_array[postid]);
continue;
}
if (!outstanding_requests[postid]) {
outstanding_requests[postid] = 1;
++number_of_outstanding_requests;
get_json(postid); //calling a function is REQUIRED to give postid its own scope
}
}
if (number_of_outstanding_requests) return;
results_to_page(datas);
}
function get_json(postid) {
var url = '//j.nozomi.la/' + postdir + '/' + path_from_postid(postid.toString()) + '.json';
var xmlhttp = new XMLHttpRequest();
xmlhttp.open('GET', url);
xmlhttp.onreadystatechange = function () {
if (this.readyState === 4) {
if (this.status === 200) {
results_array[postid] = JSON.parse(this.responseText);
} else {
results_array[postid] = '';
}
delete outstanding_requests[postid];
--number_of_outstanding_requests;
get_jsons();
}
};
xmlhttp.send();
}
function results_to_page(datas) {
var tc = Object.create(null);
var to = {};
dgebi('thumbnail-divs').innerHTML = '';
var ul = document.getElementsByClassName('title')[0].nextElementSibling;
ul.innerHTML = '';
var p = function (l) {
var areas = ['general', 'artist', 'copyright', 'character'];
for (var a in areas) {
var area = areas[a];
for (var i in l[area]) {
var tag = l[area][i];
if (tag.tag in tc === false) {
tc[tag.tag] = 1;
} else {
tc[tag.tag]++;
}
to[tag.tag] = tag;
}
}
};
for (var d in datas) {
var data = datas[d];
if (!data) continue;
var div = document.createElement('div');
div.classList.add('thumbnail-div');
var a = document.createElement('a');
a.href = '/post/' + data.postid + '.html#' + tag_for_hash;
var img = document.createElement('img');
img.classList.add('tag-list-img');
img.crossOrigin = 'Anonymous';
img.src = data.imageurl.replace(/\/\/i\.nozomi\.la\//, '//tn.nozomi.la/') + '.jpg';
img.title = data.date;
a.appendChild(img);
div.appendChild(a);
dgebi('thumbnail-divs').appendChild(div);
p(data);
}
resize_thumbnails();
setTimeout(resize_thumbnails, 10);
check_dates();
}
module.exports = {
initNozomi() {
return;
},
fetchNozomiAll() {
const totalPage = parseInt(innerText(document.querySelector('.page-container li:last-child'), 1), 10);
const totalImageCount = totalPage * 64;
// prettify page
const elementsToRemove = [
document.querySelector('.page-container'),
document.querySelector('.navbar'),
document.querySelector('.sidebar')
];
for (const elem of elementsToRemove) {
elem.style.display = 'none';
}
const mainContent = document.querySelector('.content');
mainContent.style.margin = '0 auto';
const thumbnailsContainer = document.getElementById('thumbnail-divs');
for (const e of Array.from(thumbnailsContainer.getElementsByClassName('thumbnail-div'))) {
thumbnailsContainer.removeChild(e);
}
fetch_nozomi(totalImageCount);
},
extractNozomiImages() {
let images = Array.from(document.querySelectorAll(ImgSrcSelector));
let title = document.querySelector(TitleSelector).innerText;
images = images.map(s => s.src.replace('//tn', '//i').split('.').slice(0, 4).join('.'));
return `${title}\n${images.join('\n')}\n${'= ='.repeat(20)}`;
}
};
},{"./utils":6}],6:[function(require,module,exports){
module.exports = {
isHitomi() {
return window && window.location && /hitomi/gi.test(window.location.href);
},
isNozomi() {
return window && window.location && /nozomi.la\/tag/gi.test(window.location.href);
},
isEhentai() {
return window && window.location && /e-hentai.org\/s/gi.test(window.location.href);
},
copyToClipboard(content) {
const el = document.createElement('textarea');
el.value = content;
document.body.appendChild(el);
el.select();
document.execCommand('copy');
document.body.removeChild(el);
},
href(d = '') {
return (window && window.location && window.location.href) || d;
},
innerText(elem, d = '') {
return (elem && elem.innerText) || d;
},
matchAll(content, pat) {
let matches = [];
let match = pat.exec(content);
while (match) {
matches.push(match[1]);
match = pat.exec(content);
}
pat.lastIndex = -1;
return matches;
},
createFullScreenElement(text) {
const elem = document.createElement('div');
elem.style.position = 'fixed';
elem.style.top = '0';
elem.style.right = '0';
elem.style.bottom = '0';
elem.style.left = '0';
elem.style.display = 'flex';
elem.style.backgroundColor = 'rgba(0, 0, 0, 0.56)';
elem.style.justifyContent = 'center';
elem.style.alignItems = 'center';
elem.style.fontSize = '72px';
elem.style.zIndex = '999';
elem.innerText = text;
return elem;
}
};
},{}]},{},[4]);